도순씨의 코딩일지
C++ :: STL list 컨테이너 본문
list 컨테이너는 노드 기반 컨테이너로 원소가 노드 단위로 저장됩니다. 자료구조의 이중 연결리스트로 구현됩니다.
list는 노드 기반 컨테이너이기 때문에 임의 접근 반복자가 아닌 양방향 반복자를 제공합니다. 따라서 모든 원소를 탐색하기 위해서는 양방향 반복자인 ++와 --를 사용하면 됩니다.
⭐️ list의 push_back, push_front 반복자
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
#include <iostream>
#include <list>
using namespace std;
int main(void){
list<int> lt;
lt.push_back(10);
lt.push_back(20);
lt.push_back(30);
lt.push_back(40);
lt.push_back(50);
list<int> :: iterator iter;
for(iter = lt.begin() ; iter != lt.end() ; ++iter)
cout << *iter << ' ';
cout << endl;
lt.push_front(100);
lt.push_front(200);
for(iter = lt.begin() ; iter != lt.end() ; ++iter)
cout << *iter << ' ';
cout << endl;
return 0;
}
|
cs |
⭐️ list의 push_back, push_front 반복자 실행결과
1
2
|
10 20 30 40 50
200 100 10 20 30 40 50
|
cs |
list의 특징 중 하나는 중간에 원소를 삽입하거나 제거해도 상수 시간 복잡도의 수행 성능을 보인다는 점입니다. 또한 반복자가 가리키는 원소 자체가 제거되지 않으면 반복자가 가리키는 원소는 계속 존재합니다.
⭐️ list의 insert()와 erase()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
#include <iostream>
#include <list>
using namespace std;
int main(void){
list<int> lt;
lt.push_back(10);
lt.push_back(20);
lt.push_back(30);
lt.push_back(40);
lt.push_back(50);
list<int> :: iterator iter = lt.begin();
list<int> :: iterator iter2;
++iter;
++iter;
iter2 = lt.erase(iter);
for(iter = lt.begin() ; iter != lt.end() ; ++iter)
cout << *iter << ' ';
cout << endl;
cout << "iter2: " << *iter2 << endl;
iter = iter2;
iter2 = lt.insert(iter, 300); // iter2(40)이 가리키는 위치에 300 삽입
for(iter = lt.begin() ; iter != lt.end() ; ++ iter)
cout << *iter << ' ';
cout << endl;
cout << "iter : " << *iter2 << endl;
return 0;
}
|
cs |
⭐️ list의 insert()와 erase() 실행결과
1
2
3
4
|
10 20 40 50
iter2: 40
10 20 300 40 50
iter : 300
|
cs |
다음은 list의 remove() 멤버 함수 예제입니다.
⭐️ list의 remove()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
#include <iostream>
#include <list>
using namespace std;
int main(void){
list<int> lt;
lt.push_back(10);
lt.push_back(20);
lt.push_back(30);
lt.push_back(10);
lt.push_back(40);
lt.push_back(50);
lt.push_back(10);
lt.push_back(10);
list<int> :: iterator iter;
for(iter = lt.begin() ; iter != lt.end() ; ++iter)
cout << *iter << ' ';
cout << endl;
lt.remove(10);
for(iter = lt.begin() ; iter != lt.end() ; ++ iter)
cout << *iter << ' ';
cout << endl;
return 0;
}
|
cs |
⭐️ list의 revmoe() 실행결과
1
2
|
10 20 30 10 40 50 10 10
20 30 40 50
|
cs |
remove() 함수는 값을 이용하여 노드를 제거합니다. 위에서 lt.remove(10)은 노드의 값이 10인 노드를 모두 제거하라는 뜻과 같습니다. 조건자를 이용하여 원소를 제거해야 한다면 remove_if() 멤버함수를 이용합니다.
⭐️ list의 remove_if()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
#include <iostream>
#include <list>
using namespace std;
bool Predicate(int n){
return 10 <= n && n <= 30;
}
int main(void){
list <int> lt;
lt.push_back(10);
lt.push_back(20);
lt.push_back(30);
lt.push_back(40);
lt.push_back(50);
lt.push_back(10);
list<int> :: iterator iter;
for(iter = lt.begin() ; iter != lt.end() ; ++iter)
cout << *iter << ' ';
cout << endl;
lt.remove_if(Predicate);
for(iter = lt.begin() ; iter != lt.end() ; ++iter)
cout << *iter << ' ';
cout << endl;
return 0;
}
|
cs |
⭐️ list의 remove_if() 실행결과
1
2
|
10 20 30 40 50 10
40 50
|
cs |
spice는 다른 list 컨테이너의 순차열을 잘라붙일 수 있습니다.
⭐️ list의 spice()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
#include <iostream>
#include <list>
using namespace std;
int main(void){
list<int> lt1;
list<int> lt2;
lt1.push_back(10);
lt1.push_back(20);
lt1.push_back(30);
lt1.push_back(40);
lt1.push_back(50);
lt2.push_back(100);
lt2.push_back(200);
lt2.push_back(300);
lt2.push_back(400);
lt2.push_back(500);
list<int>::iterator iter;
cout << "lt1: ";
for(iter = lt1.begin() ; iter != lt1.end() ; ++iter)
cout << *iter << ' ';
cout << endl;
cout << "lt2: ";
for(iter = lt2.begin() ; iter != lt2.end() ; ++iter)
cout << *iter << ' ';
cout << endl << "===============" << endl;
iter = lt1.begin();
++iter;
++iter;
lt1.splice(iter, lt2);
cout << "lt1: ";
for(iter = lt1.begin() ; iter != lt1.end() ; ++iter)
cout << *iter << ' ';
cout << endl;
cout << "lt2: ";
for(iter = lt2.begin() ; iter != lt2.end() ; ++iter)
cout << *iter << ' ';
cout << endl;
return 0;
}
|
cs |
⭐️ list의 spice() 실행결과
1
2
3
4
5
|
lt1: 10 20 30 40 50
lt2: 100 200 300 400 500
===============
lt1: 10 20 100 200 300 400 500 30 40 50
lt2:
|
cs |
reverse()는 이중 연결 리스트의 탐색 경로를 바꿈으로서 순차열을 리버스시킵니다.
⭐️ list의 reverse()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
#include <iostream>
#include <list>
using namespace std;
int main(){
list<int> lt;
lt.push_back(10);
lt.push_back(20);
lt.push_back(30);
lt.push_back(40);
lt.push_back(50);
list<int> :: iterator iter;
for(iter = lt.begin() ; iter != lt.end() ; ++ iter)
cout << *iter << ' ';
cout << endl;
lt.reverse();
for(iter = lt.begin() ; iter != lt.end() ; ++ iter)
cout << *iter << ' ';
cout << endl;
return 0;
}
|
cs |
⭐️ list의 reverse() 실행결과
1
2
|
10 20 30 40 50
50 40 30 20 10
|
cs |
원소를 중복되지 않게 하나씩 남기고 싶다면 unique() 멤버함수를 사용합니다. 다음 예제는 인접한 원소를 유일하게 만드는 unique() 예제입니다.
⭐️ list의 unique()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
#include <iostream>
#include <list>
using namespace std;
int main(){
list<int> lt;
lt.push_back(10);
lt.push_back(10);
lt.push_back(20);
lt.push_back(30);
lt.push_back(30);
lt.push_back(30);
lt.push_back(40);
lt.push_back(50);
lt.push_back(10);
list<int> :: iterator iter;
for(iter = lt.begin() ; iter != lt.end() ; ++iter)
cout << *iter << ' ';
cout << endl;
lt.unique();
for(iter = lt.begin() ; iter != lt.end() ; ++iter)
cout << *iter << ' ';
cout << endl;
return 0;
}
|
cs |
⭐️ list의 unique() 실행결과
1
2
|
10 10 20 30 30 30 40 50 10
10 20 30 40 50 10
|
cs |
다음은 리스트를 정렬해보도록 하겠습니다. sort() 알고리즘은 임의 접근 반복자를 지원하는 컨테이너만 사용할 수 있습니다. 때문에 list는 자체 정렬 멤버 함수 sort()를 사용합니다.
⭐️ list의 sort()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#include <iostream>
#include <list>
using namespace std;
int main(void){
list<int> lt;
lt.push_back(20);
lt.push_back(10);
lt.push_back(50);
lt.push_back(30);
lt.push_back(40);
list<int> :: iterator iter;
for(iter = lt.begin() ; iter != lt.end() ; ++iter)
cout << *iter << ' ';
cout << endl;
lt.sort();
for(iter = lt.begin() ; iter != lt.end() ; ++iter)
cout << *iter << ' ';
cout << endl;
return 0;
}
|
cs |
⭐️ list의 sort() 실행결과
1
2
|
20 10 50 30 40
10 20 30 40 50
|
cs |
두 list를 합병해야 하는 경우 merge() 멤버 함수를 사용합니다. 이 때 두 list는 정렬되어 있어야 합니다.
⭐️ list의 merge()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
#include <iostream>
#include <list>
using namespace std;
int main(){
list<int> lt1;
list<int> lt2;
lt1.push_back(10);
lt1.push_back(20);
lt1.push_back(30);
lt1.push_back(40);
lt1.push_back(50);
lt2.push_back(25);
lt2.push_back(35);
lt2.push_back(60);
list<int> :: iterator iter;
cout << "lt1: ";
for(iter = lt1.begin() ; iter != lt1.end() ; ++iter)
cout << *iter << ' ';
cout << endl;
cout << "lt2: ";
for(iter = lt2.begin() ; iter != lt2.end() ; ++iter)
cout << *iter << ' ';
cout << endl << "========================" << endl;
lt1.merge(lt2);
cout << "lt1: ";
for(iter = lt1.begin() ; iter != lt1.end() ; ++iter)
cout << *iter << ' ';
cout << endl;
cout << "lt2: " ;
for(iter = lt2.begin() ; iter != lt2.end() ; ++iter)
cout << *iter << ' ';
cout << endl;
return 0;
}
|
cs |
⭐️ list의 merge() 실행결과
1
2
3
4
5
|
lt1: 10 20 30 40 50
lt2: 25 35 60
========================
lt1: 10 20 25 30 35 40 50 60
lt2:
|
cs |
📚 출처
공동환(2012), 뇌를 자극하는 C++ STL, 한빛미디어.
'𝐏𝐑𝐎𝐆𝐑𝐀𝐌𝐌𝐈𝐍𝐆 > 𝐂++' 카테고리의 다른 글
C++ :: STL multiset 컨테이너 (0) | 2020.09.18 |
---|---|
C++ :: STL set 컨테이너 (0) | 2020.09.17 |
C++ :: STL duque 컨테이너 (0) | 2020.09.14 |
STL :: 시퀸스 컨테이너(1) (0) | 2020.09.12 |
C++ :: STL이란? (0) | 2020.09.08 |