[STL] list 정리 및 예제

2019. 7. 30. 00:31 기타/C++ STL

[STL] list 정리 및 예제


list 컨테이너는 vector와 deque 처럼 시퀀스 컨테이너로 원소가 상대적인 순서를 유지한다.

그러나 list는 노드 기반 컨테이너로 원소가 노드 단위로 저장되며 list는 이중 연결 리스트로 구현된다.


[기타/C++ STL] - [STL] vector 벡터 정리 및 예제


[기타/C++ STL] - [STL] deque 정리 및 예제



 템플릿 형식 

 template<typename T, typename Allocator=allocator<T>>

calss list

T 는 list 컨테이너 원소의 형식 



생성자 

 list lt

lt는 빈 컨테이너이다. 

 list lt(n)

lt는 기본값으로 초기화된 n개의 원소를 갖는다. 

 list lt(n, x)

lt는 x 값으로 초기화된 n개의 원소를 갖는다. 

 list lt(lt2)

lt는 lt2 컨테이너의 복사본이다 

 list lt(b,e)

lt는 반복자 구간 [b,e)로 초기화된 원소를 갖는다. 



멤버 함수 

 lt.assign(n,x)

lt에 x 값으로 n개의 원소를 할당한다. 

 lt.assign(b,e)

lt를 반복자 구간 [b,e)로 할당한다. 

 lt.back()

lt의 마지막 원소를 참조한다. 

 p=lt.begin()

p는 lt의 첫 원소를 가리키는 반복자다 

 lt.clear()

lt의 모든 원소를 제거한다. 

 lt.empty()

lt가 비었는지 조사한다. 

 p=lt.end()

p는 lt의 끝을 표식하는 반복자다 

 q=lt.erase(p)

p가 가리키는 원소를 제거한다. q는 다음 원소를 가리킨다. 

 q= lt.erase(b,e)

반복자 구간 [b,e)의 모든 원소를 제거한다. q는 다음 원소다 

 lt.front()

lt의 첫 번째 원소를 참조한다. 

q=lt.insert(p,x)

p가 가리키는 위치에 x 값을 삽입한다. q는 삽입한 원소를 가리키는 반복자다 

 lt.insert(p,n,x)

p가 가리키는 위치에 n 개의 x 값을 삽입한다. 

 lt.insert(p,b,e)

p가 가리키는 위치에 반복자 구간 [b,e)의 원소를 삽입한다. 

 x=lt.max_size()

x는 lt가 담을 수 있는 최대 원소의 개수 

 lt.merge(lt2)

lt2를 lt로 합병 정렬한다. 

 lt.merge(lt2, pred)

lt2를 lt로 합병 정렬한다. pred(조건자)를 가지누으로 합병한다. 

 lt.pop_back()

lt의 마지막 원소를 제거한다. 

 lt.pop_front()

lt의 첫번째 원소를 제거한다. 

 lt.push_back(x)

lt의 끝에 x를 추가한다. 

 lt.push_front(x)lt의 앞쪽에 x를 추가한다. 

 p=lt.rbegin()

p는 lt의 역 순차열의 첫 원소를 가리키는 반복자다 

 lt.remove(x)

x 원소를 모두 제거한다. 

 lt.remove_if(pred)

pred(단항 조건자)가 '참'인 모든 원소를 제거한다. 

 p=lt.rend()

p는 lt의 역 순차열의 첫 원소를 가리키는 반복자다 

 lt.resize(n)

lt의 크기를 n으로 변경하고 확장되는 공간의 값을 기본값으로 초기화한다. 

 lt.reverse()

lt 순차열을 뒤집는다. 
 lt.size()

lt 원소의 갯수다 

 lt.sort()lt의 모든 원소를 오름 차순 으로 정렬한다. 
 lt.sort(pred)lt의 모든 원소를 pred(조건자)를 기준으로 정렬한다. 

 lt.splice(p, lt2)

p가 가리키는 위치에 lt2의 모든 원소를 잘라 붙인다. 

 lt.splice(p, lt2, q)

p가 가리키는 위치에 lt2의 q가 가리키는 원소를 잘라 붙인다. 

 lt.splice(p, lt2, b, e)

p가 가리키는 위치에 lt2의 순차열 [b,e)를 잘라 붙인다. 

 lt.swap(lt2)

lt와 lt2를 swap 한다. 

 lt.unique()

인접한 원소의 값이 같다면 유일한 원소의 순차열로 만든다. 
 lt.unique(pred)

인접한 원소가 pred(이항 조건자)의 기준에 맞다면 유일한 원소의 순차열로 만든다 



연산자 

 lt1 == lt2

lt1과 lt2의 모든 원소가 같은가? (bool) 

 lt1 != lt2

lt1과 lt2의 모든 원소 중 하나라도 다른 원소가 있는가 

 lt1 < lt2

문자열 비교처럼 lt2가 lt1보다 큰가? 

 lt1 > lt2

문자열 비교처럼 lt1이 lt2보다 큰가? 



멤버 형식 

 allocator_type

메모리 관리자 형식 

 const_iterator

const 반복자 형식 

 const_pointer

const value_type* 형식 

 const_reference

const value_type& 형식 

 const_reverse_iterator

const 역 반복자 형식 

 difference_type

두 반복자 차이의 형식 

 iterator

반복자 형식 

 pointer

value_type* 형식 

 reference

value_type& 형식 

 reverse_iterator

역 반복자 형식 
 size_type

첨자(index)나 원소의 개수 등의 형식 

 value_type

원소의 형식 


list는 시퀀스 컨테이너로 시퀀스 컨테이너가 갖는 모든 특징을 갖는다.

list는 노드 기반 컨테이너로 at()과 [] 연산자가 없으며 임의 접근 반복자가 아닌 양방향 반복자를 제공한다.

그래서 모든 원소를 탐색하려면 양방향 반복자의 연산인 ++, --를 사용한다.


list의 가장 큰 특징 중 하나는 순 차열 중간에 원소를 삽입(insert), 제거(erase) 하더라도 상수 시간 복잡도의 수행 성능을 보인다는 점이다.

배열 기반 컨테이너 vector 나 deque 처럼 원소를 밀어내지 않고 노드를 서로 연결하기만 되기 때문이다.


또한 노드 기반 컨테이너의 삽입과 제거 동작은 반복자를 무효화시키지 않는다.

반복자가 가리키는 원소 자체가 제거되지 않는 한 반복자가 가리키는 원소는 그대로 존재한다.

하지만, 배열 기반 컨테이너(vector, deque)의 반복자는 원소의 삽입과 제거 동작이 발생하면 메모리가 재할당되거나 원소가 이동할 수 있으므로 반복자가 무효화된다.


노드 기반 컨테이너로 insert()나 erase()는 배열 기반보다 효율적으로 동작하며 값의 비교로 원소를 제거하는 remove(), remove_if()를 제공한다.


또한 list는 다른 list와 결합할 때 좋은 컨테이너이다. splice() 멤버 함수는 노드의 연결 연산만으로 두 list를 하나의 리스트로 결합할 수 있으며, merge() 멤버 함수는 두 list를 하나의 list로 정렬하며 결합한다.

또한 당양한 기능을 수행하는 reverse(), sort(), unique()등의 멤버 함수도 제공한다.


#include <iostream>
#include <list>
using namespace std;

bool Predicate(int n){
    return n >= 30;
}

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;

    iter = lt.begin();
    iter++;
    iter++;

    // erase 삭제
    list<int>::iterator iter2 = lt.erase(iter);
    for (iter = lt.begin(); iter != lt.end(); ++iter){
        cout << *iter << ' ';
    }
    cout << endl;
    cout << "iter2 : " << *iter2 << endl;

    lt.push_back(10);
    lt.push_back(10);

    for (iter = lt.begin(); iter != lt.end(); ++iter){
        cout << *iter << ' ';
    }
    cout << endl;

    // 리스트에서 원소 10 제거
    lt.remove(10);

    for (iter = lt.begin(); iter != lt.end(); ++iter){
        cout << *iter << ' ';
    }
    cout << endl;


    // Predicate 함수에 해당하는 원소 제거 (30보다 크다)
    lt.remove_if(Predicate);

    for (iter = lt.begin(); iter != lt.end(); ++iter){
        cout << *iter << ' ';
    }
    cout << endl;

    return 0;
}



 결과 :

10 20 30 40 50

10 20 40 50

iter2 : 40

10 20 40 50 10 10

20 40 50

20



#include <iostream>
#include <list>
using namespace std;

bool Predicate(int first, int second){
    return second-first >=0;
}

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(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;        //30 원소의 위치를 가리킴

    lt1.splice(iter, lt2); // iter가 가리키는 위치(30)에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 << "==================" << endl;

    lt1.reverse();    // 리스트 역순 뒤집기

    cout << "lt1 reverse : ";
    for (iter = lt1.begin(); iter != lt1.end(); ++iter){
        cout << *iter << ' ';
    }
    cout << endl << "==================" << endl;

    lt1.push_front(50);
    lt1.push_front(50);
    lt1.push_back(10);
    lt1.push_back(50);

    cout << "lt1 : ";
    for (iter = lt1.begin(); iter != lt1.end(); ++iter){
        cout << *iter << ' ';
    }
    cout << endl;

    lt1.unique();        // 인접한 중복 원소를 합친다.

    cout << "lt1 unique : ";
    for (iter = lt1.begin(); iter != lt1.end(); ++iter){
        cout << *iter << ' ';
    }
    cout << endl;

    lt1.unique(Predicate);    // Predicate에 따라 다음 원소가 크거나 같으면 제거한다.

    cout << "lt1 unique Predicate: ";
    for (iter = lt1.begin(); iter != lt1.end(); ++iter){
        cout << *iter << ' ';
    }
    cout << endl << "==================" << endl;

    lt1.sort();    // 오름차순으로 정렬한다.

    cout << "lt1 sort : ";
    for (iter = lt1.begin(); iter != lt1.end(); ++iter){
        cout << *iter << ' ';
    }
    cout << endl << "==================" << endl;

    lt2.push_back(30);
    lt2.push_back(60);
    lt2.push_back(10);
    lt2.push_back(99);
    lt2.sort();
    
    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;

    lt1.merge(lt2);    // lt1에 lt2를 오름차순 정렬 순서로 합병한다.

    cout << "lt1 merge : ";
    for (iter = lt1.begin(); iter != lt1.end(); ++iter){
        cout << *iter << ' ';
    }
    cout << endl;

    cout << "lt2  merge : ";
    for (iter = lt2.begin(); iter != lt2.end(); ++iter){
        cout << *iter << ' ';
    }
    cout << endl;

    return 0;
}



결과 :

lt1 : 10 20 30 40 50

lt2 : 100 200 300 400 500

=================

lt1 : 10 20 100 200 300 400 500 30 40 50

lt2 :

=================

lt1 reverse : 50 40 30 500 400 300 200 100 20 10

=================

lt1 : 50 50 50 40 30 500 400 300 200 100 20 10 10 50

lt1 unique : 50 40 30 500 400 300 200 100 20 10 50

lt1 unique Predicate : 50 40 30 20 10

================

lt1 sort : 10 20 30 40 50

================

lt1 : 10 20 30 40 50

lt2 : 10 30 60 99

lt1 merge : 10 10 20 30 30 40 50 60 99

lt2 merge :



- splice() 를 사용하면, 다른 리스트의 원소를 잘라서 붙일 수 있다.

- merge() 와의 차이점은 합병하면서 정렬을 수행한다. 따라서 merge는 lt1과 lt2가 오름차순 정렬되어 있다는 가정하에 동작한다.

만약 lt1이나 lt2가 정렬 기준이 틀렸거나 합형할 list가 정렬되어 있지 않다면 merge() 함수는 실패하며 오류가 발생한다.



출처: https://hyeonstorage.tistory.com/326?category=614599 [개발이 하고 싶어요]

'기타 > C++ STL' 카테고리의 다른 글

[STL] multimap 정리 및 예제  (0) 2019.07.30
[STL] map 정리 및 예제  (0) 2019.07.30
[STL] multiset 정리 및 예제  (0) 2019.07.30
[STL] set 정리 및 예제  (0) 2019.07.30
[STL] deque 정리 및 예제  (0) 2019.07.30
[STL] vector 벡터 정리 및 예제  (0) 2019.07.30
[STL] not2 함수  (0) 2019.07.30
[STL] 역방향 반복자 (reverse_iterator)  (1) 2019.07.30