그룹액티비티 1번문제
Node *func(Node *head, int *j)
{
Node* t1, * t2;
*j = 0;
t1 = head;
if (t1 != nullptr) t2 = t1->next;
else return head;
*j = 1;
if (t2 == nullptr)
return head;
while(t2 != nullptr)
{
if(t1->data != t2->data)
{
(*j)++; t1->next = t2; t1 = t2;
}
t2 = t2->next;
}
t1->next = nullptr;
return head;
}
1. 함수가 하는 일:
이 함수는 연결 리스트에서 중복된 값을 제거하는 역할을 합니다. 연결 리스트의 노드들이 오른차순으로 정렬되어 있다고 가정하고, 리스트를 순차적으로 탐색하면서 중복된 값을 찾아 제거합니다. 함수는 리스트에서 각 노드의 값을 비교하여 중복된 노드를 삭제하고, 중복이 없는 리스트를 반환합니다.
2. 매개변수 j의 역할:
매개변수 j는 중복된 노드를 제거하는 동안 몇 번의 중복이 발생했는지를 세는 역할을 합니다. 이 변수는 함수 내에서 중복된 노드가 발견될 때마다 ++ 연산을 통해 값이 증가합니다. 즉, 함수가 제거한 중복 노드의 수를 추적합니다.
3. S1과 S2가 실행되는 횟수:
- S1 (if (t1->data != t2->data))는 t1과 t2의 데이터가 다른지 비교하는 조건문입니다. 리스트를 순차적으로 탐색하며 비교를 계속하기 때문에, 리스트의 모든 노드를 검사합니다. 리스트의 길이가 n일 때, 이 조건문은 최대 n-1번 실행될 수 있습니다.
- S2 ((*j)++; t1->next = t2; t1 = t2;)는 중복된 노드가 발견되지 않을 때 실행됩니다. 이 문장은 t1과 t2의 데이터가 다를 때 실행되므로, 중복이 아닌 노드가 발견될 때마다 실행됩니다. S2는 중복된 값을 제거하는 것이므로 최대 n-1번까지 실행될 수 있습니다.
요약:
- 이 함수는 연결 리스트에서 중복된 값을 제거하는 역할을 합니다.
- 매개변수 j는 중복된 값이 발생한 횟수를 추적하는 데 사용됩니다.
- 리스트의 길이가 n >= 2일 때, S1과 S2가 실행되는 횟수는 리스트의 길이에 따라 각각 최대 n-1번입니다.
자료구조 2번
struct Node {
int data;
Node* next;
};
Node* merge(Node* first, Node* second) {
// 두 리스트 중 하나가 비어 있으면 다른 리스트 반환
if (first == NULL) return second;
if (second == NULL) return first;
// 병합된 리스트의 첫 번째 노드를 결정
Node* result;
if (first->data < second->data) {
result = first;
result->next = merge(first->next, second); // 재귀적으로 병합
} else {
result = second;
result->next = merge(first, second->next); // 재귀적으로 병합
}
return result;
}
설명:
- 구조체 Node: Node는 정수형 데이터를 저장하는 단순한 연결 리스트 노드입니다. 이 구조체는 data 필드와 다음 노드를 가리키는 next 포인터로 구성됩니다.
- 기본 조건: 리스트가 비어 있는 경우 다른 리스트를 반환합니다. 이는 재귀적으로 호출될 때 어느 한쪽 리스트가 더 이상 노드를 가지고 있지 않을 때 종료 조건으로 작용합니다.
- 첫 번째 노드 선택: 두 리스트의 첫 번째 노드 데이터를 비교하여 작은 값을 가진 노드를 result로 설정합니다. 그런 다음, 해당 노드의 next를 병합된 나머지 리스트의 결과로 설정합니다.
- 재귀 호출: 작은 값을 가진 노드를 선택하고, 나머지 노드들은 재귀적으로 병합됩니다.
이 방식은 재귀적으로 연결 리스트를 병합하는 방식이며, 새로 노드를 생성하지 않고 기존의 노드들만을 이용하여 병합합니다.
자료구조 3번
void func(Node *head) {
Node *p = head, *q = nullptr;
while (p != nullptr) {
if (p->data < 0)
q->next = p->next; // q가 nullptr일 경우 문제가 발생할 수 있음
else
q = p; // q는 음수가 아닌 노드를 가리키게 함
p = p->next; // p는 다음 노드로 이동
}
}
함수가 하려는 일:
이 함수는 연결 리스트에서 데이터를 가진 노드가 음수인 경우 해당 노드를 제거하고, 음수가 아닌 노드끼리 연결하는 일을 하려는 것 같습니다.
문제점:
- 초기값 문제: q가 처음에 nullptr로 초기화되어 있습니다. 리스트의 첫 번째 노드가 음수일 경우, q->next = p->next;에서 q가 아직 nullptr이기 때문에, nullptr에서 next를 참조하려고 하면 런타임 오류가 발생합니다.
- 첫 번째 노드가 음수일 때: 첫 번째 노드가 음수라면 q가 제대로 리스트의 연결을 담당하지 못하므로, 리스트의 시작 부분이 손상될 수 있습니다.
수정 방안:
- q가 nullptr일 때를 처리: q가 nullptr일 때, 즉 첫 번째 노드를 처리할 때 특별한 처리를 추가해줘야 합니다. q가 nullptr이면 head를 직접 수정하는 방식으로 문제를 해결할 수 있습니다.
- 첫 번째 노드가 음수일 때 헤드를 처리: 음수를 포함한 첫 번째 노드를 처리하는 특별한 논리가 필요합니다.
void func(Node *&head) {
Node *p = head, *q = nullptr;
while (p != nullptr) {
if (p->data < 0) {
if (q == nullptr) {
// 첫 번째 노드가 음수인 경우 head를 갱신
head = p->next;
} else {
// q가 가리키는 노드의 next를 갱신하여 음수 노드를 건너뜀
q->next = p->next;
}
} else {
q = p; // q는 음수가 아닌 노드를 가리킴
}
p = p->next; // p는 다음 노드로 이동
}
}
수정 사항 설명:
- q가 nullptr일 때는 리스트의 첫 번째 노드를 처리하는 경우로, 헤드를 직접 갱신하여 음수 노드를 제거합니다.
- 나머지 경우에는 q가 p의 이전 노드를 가리키며, p가 음수이면 q->next를 조정하여 음수 노드를 건너뜁니다.
이렇게 수정하면 첫 번째 노드가 음수일 때도 안전하게 리스트에서 제거할 수 있으며, 나머지 음수 노드도 정상적으로 처리됩니다.
자료구조 4번
struct Node {
int data;
Node* next;
};
Node* deleteNodesInRange(Node* head, int lower, int upper) {
// 먼저 head가 삭제 대상일 수 있으므로 head부터 처리
while (head != nullptr && head->data >= lower && head->data <= upper) {
Node* temp = head;
head = head->next; // head를 다음 노드로 이동
delete temp; // 현재 head 노드 삭제
}
// 현재 리스트가 비었거나 범위 밖이라면 종료
if (head == nullptr) return nullptr;
// 나머지 리스트 탐색
Node* current = head;
while (current->next != nullptr) {
// 다음 노드가 삭제 범위에 들어가면 삭제
if (current->next->data >= lower && current->next->data <= upper) {
Node* temp = current->next;
current->next = current->next->next; // 노드 건너뜀
delete temp; // 해당 노드 삭제
} else {
current = current->next; // 다음 노드로 이동
}
}
return head;
}
자료구조 5번
#include <iostream>
#include <list>
using namespace std;
int main() {
list<int> first; // 빈 리스트 생성
list<int> second(4,100); // 100이 4개 있는 리스트 생성: [100, 100, 100, 100]
list<int> third(second.begin(), second.end()); // second의 모든 원소로 third 리스트 생성: [100, 100, 100, 100]
list<int> fourth(third); // third 리스트로 fourth 리스트 복사: [100, 100, 100, 100]
int myints[] = {16, 2, 77, 29}; // 배열 선언
list<int> fifth(myints, myints + sizeof(myints)/sizeof(int)); // 배열로 리스트 fifth 생성: [16, 2, 77, 29]
for (auto it = fifth.begin(); it != fifth.end(); it++) // fifth 리스트 출력
cout << *it << ' ';
cout << '\n';
return 0;
}
- first 리스트: 빈 리스트입니다. 아무런 원소도 없습니다.
- second 리스트: 4개의 100으로 초기화된 리스트입니다.
-
second = [100, 100, 100, 100]
- third 리스트: second 리스트의 모든 원소를 복사하여 만든 리스트입니다.
-
third = [100, 100, 100, 100]
- fourth 리스트: third 리스트의 모든 원소를 복사하여 만든 리스트입니다.
fourth = [100, 100, 100, 100]
- fifth 리스트: 배열 myints[]를 사용하여 리스트를 초기화합니다.
이 부분은 fifth 리스트의 모든 원소를 출력하는 코드입니다. fifth 리스트는 배열 myints[]로 초기화되었으므로, 출력 결과는 배열의 원소들인 16, 2, 77, 29가 순서대로 출력됩니다.
#include <iostream>
#include <list>
using namespace std;
int main () {
list<int> first {1, 2, 3}; // 리스트 first 초기화: [1, 2, 3]
list<int> second {10, 20, 30, 40, 50}; // 리스트 second 초기화: [10, 20, 30, 40, 50]
second = first; // second 리스트에 first 리스트 할당: second = [1, 2, 3]
auto it = first.begin(); // first 리스트의 첫 번째 원소를 가리키는 iterator
*it = 100; // 첫 번째 원소 값을 100으로 변경: first = [100, 2, 3]
// 첫 번째 for 루프: first 리스트 출력
for (auto a : first)
cout << a << ' '; // 출력: 100 2 3
cout << endl;
// 두 번째 for 루프: second 리스트 출력 (현재 second는 first와 같음)
for (auto b : second)
cout << b << ' '; // 출력: 1 2 3 (할당된 이후에 변경된 first의 영향을 받지 않음)
cout << endl;
// 세 번째 for 루프: second 리스트 원소들을 1씩 증가
for (auto &c : second)
c += 1; // second = [2, 3, 4]
// 네 번째 for 루프: 수정된 second 리스트 출력
for (auto c : second)
cout << c << ' '; // 출력: 2 3 4
cout << endl;
return 0;
}
상세한 동작 과정:
- 리스트 first와 second 초기화:
- first 리스트는 [1, 2, 3]으로 초기화됩니다.
- second 리스트는 [10, 20, 30, 40, 50]으로 초기화됩니다.
- second = first:
- second 리스트가 first 리스트와 동일하게 설정됩니다.
- 이때, second는 [1, 2, 3]으로 바뀌고, 이전의 [10, 20, 30, 40, 50] 값은 없어집니다.
- *it = 100:
- it는 first.begin()이므로, first 리스트의 첫 번째 원소를 가리킵니다.
- 따라서 first의 첫 번째 값이 100으로 바뀝니다.
- 이제 first는 [100, 2, 3]이 됩니다.
- 첫 번째 for 루프:
- first 리스트의 모든 원소를 출력합니다.
- 출력: 100 2 3
- 두 번째 for 루프:
- second 리스트의 모든 원소를 출력합니다.
- second는 first 리스트의 복사본이었지만, 그 후 first 리스트가 변경되었어도 second 리스트에는 영향을 주지 않습니다. second는 [1, 2, 3] 그대로입니다.
- 출력: 1 2 3
- 세 번째 for 루프:
- second 리스트의 각 원소에 1을 더합니다.
- 이제 second는 [2, 3, 4]로 바뀝니다.
- 네 번째 for 루프:
- 수정된 second 리스트의 모든 원소를 출력합니다.
- 출력: 2 3 4
#include <iostream>
#include <list>
using namespace std;
int main () {
list<int> first; // 정수형 리스트 first 선언
list<int> second; // 정수형 리스트 second 선언
first.assign(5, 100); // first에 100을 5개 추가: [100, 100, 100, 100, 100]
second.assign(first.begin(), first.end()); // second에 first 리스트 복사: [100, 100, 100, 100, 100]
int myints[] = {17, 7, 4}; // 배열 myints 선언
first.assign(myints, myints + 3); // first 리스트에 myints의 값으로 할당: [17, 7, 4]
// 첫 번째 for 루프: first 리스트 출력
for (auto a : first)
cout << a << ' '; // 출력: 17 7 4
cout << endl;
// 두 번째 for 루프: second 리스트 출력
for (auto b : second)
cout << b << ' '; // 출력: 100 100 100 100 100
cout << endl;
return 0;
}
리스트 할당 과정:
- first.assign(5, 100):
- first 리스트에 100이 5개 추가됩니다.
- 결과적으로 first = [100, 100, 100, 100, 100]
- second.assign(first.begin(), first.end()):
- second 리스트에 first 리스트의 모든 요소를 복사합니다.
- 결과적으로 second = [100, 100, 100, 100, 100]
- first.assign(myints, myints + 3):
- 배열 myints[]의 값을 first 리스트에 복사합니다.
- 배열의 크기는 3이므로 first = [17, 7, 4]
출력 과정:
- 첫 번째 for 루프:
- first 리스트의 모든 원소를 출력합니다.
- first는 [17, 7, 4]이므로, 출력 결과는 17 7 4입니다.
- 두 번째 for 루프:
- second 리스트의 모든 원소를 출력합니다.
- second는 [100, 100, 100, 100, 100]이므로, 출력 결과는 100 100 100 100 100입니다.
17 7 4
100 100 100 100 100
#include <iostream>
#include <list>
using namespace std;
int main() {
list<int> mylist(2, 100); // 100을 두 개 저장한 리스트: [100, 100]
mylist.push_front(200); // 리스트 맨 앞에 200 추가: [200, 100, 100]
mylist.push_front(300); // 리스트 맨 앞에 300 추가: [300, 200, 100, 100]
for (auto it = mylist.begin(); it != mylist.end(); ++it)
cout << *it << ' '; // 리스트의 모든 원소를 출력
cout << '\n';
return 0;
}
실행 결과:
- 초기 리스트는 [100, 100]입니다.
- push_front(200)을 호출하면 리스트 맨 앞에 200이 추가되어 [200, 100, 100]이 됩니다.
- 다시 push_front(300)을 호출하면 리스트 맨 앞에 300이 추가되어 [300, 200, 100, 100]이 됩니다.
- 리스트의 모든 원소를 출력하므로 결과는 다음과 같습니다:
#include <iostream>
#include <list>
using namespace std;
int main() {
list<int> mylist;
mylist.push_back(100); // 리스트 맨 뒤에 100 추가: [100]
mylist.push_back(200); // 리스트 맨 뒤에 200 추가: [100, 200]
mylist.push_back(300); // 리스트 맨 뒤에 300 추가: [100, 200, 300]
while (!mylist.empty()) {
cout << ' ' << mylist.front(); // 리스트의 첫 번째 원소 출력
mylist.pop_front(); // 첫 번째 원소 삭제
}
return 0;
}
실행 결과:
- 초기 리스트는 빈 리스트입니다.
- push_back(100), push_back(200), push_back(300)을 통해 리스트는 [100, 200, 300]이 됩니다.
- while 루프에서는 mylist.front()로 첫 번째 원소를 출력한 뒤, pop_front()로 첫 번째 원소를 제거합니다.
#include <iostream>
#include <list>
#include <vector>
using namespace std;
int main() {
list<int> mylist;
for (int i = 1; i <= 5; ++i)
mylist.push_back(i); // 1부터 5까지 저장한 리스트: [1, 2, 3, 4, 5]
list<int>::iterator it = mylist.begin();
++it; // it은 리스트의 두 번째 원소를 가리킴 (2)
mylist.insert(it, 10); // 두 번째 원소 앞에 10 삽입: [1, 10, 2, 3, 4, 5]
mylist.insert(it, 2, 20); // 두 번째 원소 앞에 20을 두 번 삽입: [1, 20, 20, 10, 2, 3, 4, 5]
vector<int> myvector(2, 30); // 벡터 생성: [30, 30]
mylist.insert(it, myvector.begin(), myvector.end()); // 두 번째 원소 앞에 벡터 삽입: [1, 30, 30, 20, 20, 10, 2, 3, 4, 5]
for (it = mylist.begin(); it != mylist.end(); ++it)
cout << *it << ' '; // 리스트의 모든 원소를 출력
cout << '\n';
return 0;
}
실행 결과:
- 초기 리스트는 [1, 2, 3, 4, 5]입니다.
- ++it로 it는 두 번째 원소인 2를 가리킵니다.
- insert(it, 10)로 2 앞에 10을 삽입하므로 리스트는 [1, 10, 2, 3, 4, 5]가 됩니다.
- insert(it, 2, 20)으로 2 앞에 20을 두 번 삽입하므로 리스트는 [1, 20, 20, 10, 2, 3, 4, 5]가 됩니다.
- 벡터 [30, 30]을 두 번째 원소 앞에 삽입하므로 최종 리스트는 [1, 30, 30, 20, 20, 10, 2, 3, 4, 5]가 됩니다.
#include <iostream>
#include <list>
int main() {
std::list<int> mylist1, mylist2;
std::list<int>::iterator it;
// mylist1에 1, 2, 3, 4 추가
for (int i = 1; i <= 4; ++i)
mylist1.push_back(i); // mylist1 = [1, 2, 3, 4]
// mylist2에 10, 20, 30 추가
for (int i = 1; i <= 3; ++i)
mylist2.push_back(i * 10); // mylist2 = [10, 20, 30]
it = mylist1.begin();
++it; // it은 mylist1의 두 번째 원소(2)를 가리킴
// mylist2의 모든 원소를 mylist1의 두 번째 위치에 삽입
mylist1.splice(it, mylist2); // mylist1 = [1, 10, 20, 30, 2, 3, 4], mylist2는 빈 리스트가 됨
// mylist2의 비어있는 리스트에 mylist1의 처음부터 두 번째 원소 앞까지를 다시 삽입
mylist2.splice(mylist2.begin(), mylist1, mylist1.begin(), it); // mylist2 = [1], mylist1 = [10, 20, 30, 2, 3, 4]
it = mylist1.begin();
std::advance(it, 3); // it을 세 번째 위치로 이동 (mylist1의 30을 가리킴)
// mylist1의 처음부터 세 번째 원소 앞까지를 mylist1의 끝으로 이동
mylist1.splice(mylist1.begin(), mylist1, it, mylist1.end()); // mylist1 = [30, 2, 3, 4, 10, 20]
// mylist1의 모든 원소 출력
for (it = mylist1.begin(); it != mylist1.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
// mylist2의 모든 원소 출력
for (it = mylist2.begin(); it != mylist2.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
실행 과정 및 결과:
- mylist1 초기값: [1, 2, 3, 4]
- mylist2 초기값: [10, 20, 30]
- mylist2의 원소들이 mylist1의 두 번째 위치에 삽입됩니다. mylist1 = [1, 10, 20, 30, 2, 3, 4]가 되고, mylist2는 비어 있습니다.
- mylist1의 첫 번째 원소(1)를 mylist2로 옮기고, mylist2 = [1]가 됩니다. mylist1 = [10, 20, 30, 2, 3, 4]가 됩니다.
- mylist1의 세 번째 원소(30)부터 끝까지 처음으로 이동시키면, mylist1 = [30, 2, 3, 4, 10, 20]가 됩니다.
- mylist1의 모든 원소를 출력하면: 30 2 3 4 10 20
- mylist2의 모든 원소를 출력하면: 1
#include <iostream>
#include <list>
using namespace std;
int main() {
int myints[] = {17, 89, 7, 14}; // 배열 초기화
list<int> mylist (myints, myints + 4); // 배열의 값으로 리스트 생성: [17, 89, 7, 14]
mylist.remove(89); // 리스트에서 89 삭제: [17, 7, 14]
// 리스트의 모든 원소 출력
for (auto it = mylist.begin(); it != mylist.end(); ++it)
cout << ' ' << *it;
cout << '\n';
return 0;
}
실행 과정 및 결과:
- mylist는 [17, 89, 7, 14]로 초기화됩니다.
- mylist.remove(89)는 리스트에서 89를 삭제합니다. 결과적으로 mylist = [17, 7, 14]가 됩니다.
- 리스트의 모든 원소를 출력하면: 17 7 14
#include <iostream>
#include <list>
bool single_digit(const int& value) {
return (value < 10);
}
bool is_odd(const int& value) {
return (value % 2) == 1;
}
int main() {
int myints[] = {15, 36, 7, 17, 20, 39, 4, 1};
std::list<int> mylist(myints, myints + 8); // 배열의 값으로 리스트 생성: [15, 36, 7, 17, 20, 39, 4, 1]
mylist.remove_if(single_digit); // 한 자리 숫자 제거: [15, 36, 17, 20, 39]
mylist.remove_if(is_odd); // 홀수 제거: [36, 20]
for (auto it = mylist.begin(); it != mylist.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
실행 과정 및 결과:
- myints[] 배열을 기반으로 리스트 생성: mylist = [15, 36, 7, 17, 20, 39, 4, 1]
- mylist.remove_if(single_digit): 한 자리 숫자를 삭제하므로, mylist = [15, 36, 17, 20, 39]가 됩니다.
- mylist.remove_if(is_odd): 홀수를 삭제하므로, 최종적으로 mylist = [36, 20]가 됩니다.
- 리스트의 모든 원소를 출력하면 36 20이 출력됩니다.
#include <iostream>
#include <cmath>
#include <list>
bool same_integral_part(double first, double second) {
return int(first) == int(second);
}
struct is_near {
bool operator() (double first, double second) {
return fabs(first - second) < 5.0;
}
};
int main() {
double mydoubles[] = {12.15, 2.72, 73.0, 12.77, 3.14, 12.77, 73.35, 72.25, 15.3, 72.25};
std::list<double> mylist(mydoubles, mydoubles + 10);
mylist.sort(); // 리스트를 정렬
mylist.unique(); // 중복 제거: 동일한 값을 연달아 나타나는 중복만 제거
mylist.unique(same_integral_part); // 정수 부분이 같은 값 제거
mylist.unique(is_near()); // 두 값의 차가 5.0 미만인 경우 제거
for (auto it = mylist.begin(); it != mylist.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
실행 과정 및 결과:
- mydoubles[] 배열을 기반으로 리스트 생성: mylist = [12.15, 2.72, 73.0, 12.77, 3.14, 12.77, 73.35, 72.25, 15.3, 72.25]
- mylist.sort(): 리스트를 오름차순으로 정렬하면, mylist = [2.72, 3.14, 12.15, 12.77, 12.77, 15.3, 72.25, 72.25, 73.0, 73.35]
- mylist.unique(): 연속된 중복 값 제거. 12.77, 72.25가 중복되므로 삭제되고, mylist = [2.72, 3.14, 12.15, 12.77, 15.3, 72.25, 73.0, 73.35]
- mylist.unique(same_integral_part): 정수 부분이 같은 값 제거. 즉, 12.xx 값 중 하나만 남기고 삭제, 72.xx, 73.xx 값들도 하나만 남김. 결과는 mylist = [2.72, 3.14, 12.15, 72.25]
- mylist.unique(is_near()): 값들의 차이가 5 미만인 경우 제거. 여기서는 제거 대상 없음.
- 리스트의 모든 원소를 출력하면 2.72 3.14 12.15 72.25가 출력됩니다.
#include <iostream>
#include <list>
#include <string>
#include <cctype> // tolower 함수 사용을 위해 추가
using namespace std;
// 대소문자 구분 없이 문자열을 비교하는 함수
bool compare_nocase(const string &first, const string &second) {
unsigned int i = 0;
// 두 문자열의 각 문자를 소문자로 변환하여 비교
while (i < first.length() && i < second.length()) {
if (tolower(first[i]) < tolower(second[i]))
return true;
else if (tolower(first[i]) > tolower(second[i]))
return false;
++i;
}
// 길이가 짧은 문자열을 우선으로 비교
return first.length() < second.length();
}
int main() {
list<string> mylist;
list<string>::iterator it;
// 리스트에 문자열 추가
mylist.push_back("one");
mylist.push_back("two");
mylist.push_back("Three");
// 기본 정렬 (대소문자를 구분하여 정렬)
mylist.sort();
for (it = mylist.begin(); it != mylist.end(); ++it)
cout << ' ' << *it;
cout << '\n';
// 대소문자 구분 없이 정렬
mylist.sort(compare_nocase);
for (it = mylist.begin(); it != mylist.end(); ++it)
cout << ' ' << *it;
cout << '\n';
return 0;
}
실행 과정:
- 리스트에 문자열 추가:
- mylist 리스트에 "one", "two", "Three"가 차례대로 추가됩니다.
- 리스트의 초기 상태는: ["one", "two", "Three"]
- 기본 정렬 (mylist.sort()):
- 기본 정렬은 대소문자를 구분하여 이루어집니다. 대문자가 소문자보다 ASCII 값이 작으므로, "Three"가 가장 앞에 오고, 그 다음 "one", "two"가 옵니다.
- 정렬 결과: ["Three", "one", "two"]
- 대소문자 구분 없이 정렬 (mylist.sort(compare_nocase)):
- compare_nocase 함수는 대소문자 구분 없이 문자열을 비교합니다. 따라서 "one", "Three", "two"가 대소문자 상관없이 사전 순으로 정렬됩니다.
- 정렬 결과: ["one", "Three", "two"]
함수설명
1. std::list::sort
void sort();
template <class Compare> void sort(Compare comp);
설명:
- 기본 정렬: sort()는 대소문자 구분을 포함하여 리스트의 원소들을 기본적으로 오름차순으로 정렬합니다. 즉, 원소들의 데이터 타입이 기본적으로 제공하는 < 연산자를 사용합니다.
- 사용자 정의 비교 함수 정렬: sort(Compare comp)는 사용자가 정의한 비교 함수 comp에 따라 리스트를 정렬합니다. 비교 함수는 두 개의 인자를 받아야 하며, 첫 번째 인자가 두 번째 인자보다 작을 때 true를 반환해야 합니다.
예시:
mylist.sort(); // 기본 정렬
mylist.sort(compare_nocase); // 사용자 정의 함수인 compare_nocase를 사용하여 정렬
2. std::list::remove_if
template <class Predicate> void remove_if(Predicate pred);
설명:
리스트 내의 원소 중에서 주어진 조건(pred)을 만족하는 원소들을 제거합니다. pred는 논리적 참(true) 또는 거짓(false)을 반환하는 함수 포인터 또는 함수 객체여야 합니다.
예시:
bool single_digit(const int& value) {
return (value < 10); // 10 미만의 숫자를 찾음
}
mylist.remove_if(single_digit); // 10 미만의 숫자를 모두 제거
3. std::list::splice
void splice(iterator position, list& x);
void splice(iterator position, list& x, iterator i);
void splice(iterator position, list& x, iterator first, iterator last);
설명:
- 리스트 x의 모든 원소 또는 특정 범위의 원소를 현재 리스트(this)의 position 위치에 삽입합니다.
- 첫 번째 형태: x의 모든 원소를 position 위치에 삽입합니다.
- 두 번째 형태: x의 i 위치에 있는 단일 원소를 position에 삽입합니다.
- 세 번째 형태: x의 first부터 last까지의 원소를 position에 삽입합니다.
예시:
mylist1.splice(it, mylist2); // mylist2의 모든 원소를 mylist1의 it 위치에 삽입
mylist1.splice(it, mylist2, mylist2.begin(), mylist2.end()); // mylist2의 범위 지정
4. std::list::remove
void remove(const T& value);
설명:
리스트에서 주어진 값 value를 가진 모든 원소를 제거합니다.
예시:
mylist.remove(89); // 리스트에서 89를 가진 모든 원소 제거
5. std::list::unique
void unique();
template <class BinaryPredicate> void unique(BinaryPredicate binary_pred);
설명:
- 기본 중복 제거: 리스트 내에서 연속된 중복 원소를 제거합니다. 연속된 값들 중 하나만 남깁니다.
- 사용자 정의 조건 중복 제거: unique(BinaryPredicate binary_pred)는 사용자가 정의한 조건에 따라 연속된 중복 원소를 제거합니다.
예시:
mylist.unique(); // 연속된 중복 원소 제거
mylist.unique(same_integral_part); // 정수 부분이 동일한 원소 제거
6. std::advance
void advance(InputIterator& it, Distance n);
설명:
입력된 반복자 it을 n만큼 전진시킵니다. 즉, 반복자를 n번 만큼 이동시킵니다.
예시:
std::list<int>::iterator it = mylist.begin();
std::advance(it, 3); // 반복자를 3칸 이동
7. std::fabs
double fabs(double x);
설명:
절대값을 반환합니다. 주어진 실수 값 x의 절대값을 반환하는 함수입니다.
예시:
fabs(5.0 - 3.0); // 결과는 2.0
8. std::tolower
int tolower(int ch);
설명:
주어진 문자 ch를 소문자로 변환합니다. 문자가 대문자인 경우 소문자로 변환하고, 그렇지 않은 경우 그대로 반환합니다.
예시:
tolower('A'); // 'a' 반환
tolower('b'); // 'b' 그대로 반환
9. 사용자 정의 함수들
1. compare_nocase
bool compare_nocase(const string& first, const string& second) {
unsigned int i = 0;
while (i < first.length() && i < second.length()) {
if (tolower(first[i]) < tolower(second[i]))
return true;
else if (tolower(first[i]) > tolower(second[i]))
return false;
++i;
}
return first.length() < second.length();
}
- 두 문자열을 대소문자 구분 없이 비교합니다. tolower()를 사용하여 두 문자열의 각 문자를 소문자로 변환하여 비교하고, 길이가 짧은 문자열이 우선시됩니다.
2. single_digit
bool single_digit(const int& value) {
return (value < 10);
}
- 주어진 값이 한 자리 숫자인지를 확인합니다. 값이 10 미만인 경우 true를 반환하고, 그렇지 않은 경우 false를 반환합니다.
3. is_odd
bool is_odd(const int& value) {
return (value % 2) == 1;
}
- 주어진 값이 홀수인지를 확인합니다. 값이 홀수인 경우 true, 그렇지 않은 경우 false를 반환합니다.
4. same_integral_part
bool same_integral_part(double first, double second) {
return int(first) == int(second);
}
- 두 실수 값의 정수 부분이 같은지 확인합니다. 두 값의 정수 부분이 같으면 true를 반환하고, 그렇지 않으면 false를 반환합니다.
5. is_near
struct is_near {
bool operator() (double first, double second) {
return fabs(first - second) < 5.0;
}
};
- 두 실수 값이 5.0 미만의 차이를 가지는지를 확인합니다. 두 값의 차이가 5 미만이면 true, 그렇지 않으면 false를 반환하는 함수 객체입니다.
'IT 프로그래밍 > 자료구조' 카테고리의 다른 글
[자료구조] 노래찾기 (2) | 2024.10.23 |
---|---|
[자료구조] 과제2 (2) | 2024.10.23 |
[자료구조] 그룹 엑티비티 3 전문 (1) | 2024.10.22 |
[자료구조] 그룹 액티비티 3 (0) | 2024.10.22 |
[자료구조] 프로그래밍 과제1 (0) | 2024.10.20 |