STL序列式容器之list

一、概述

list使用一個雙向鏈表來管理數據。使用list必須含入頭文件<list>,其型別定義如下:

namespace std{
    template <class T,
              class Allocator = allocator<T> >
    class list;
}

list不支持隨機存取,所以既不提供下標操作符,也不提供at()。list相較於vector的好處是每次插入或者刪除一個元素,就配置或者釋放一個元素空間。對於任何位置的元素插入或元素移除,list永遠是常數時間。

二、list內部結構

list本身和list節點是不同的結構,需要分開設計,STL list節點結構如下:

template <class T>
struct __list_node {
    typedef void* void_pointer;
    void_pointer prev;
    void_pointer next;
}

SGI list不僅是一個雙向鏈表,而且還是一個環狀雙向鏈表,結構圖如下
這裏寫圖片描述

三、list的操作函數

1. 生成、複製和銷燬

操作 效果
list<Elem> c 產生一個存放Elem類型元素的空list
list<Elem> c1(c2) 產生一個與c2同型的list,每個元素都被複制
list<Elem> c(n) 產生一個含有n個元素,以default構造函數產生元素的list
list<Elem> c(n,elem) 產生一個含有n個elem元素的list
list<Elem> c(beg,end) 產生一個以區間[beg,end]內元素爲初值的list
c.~list<Elem>() 銷燬所有元素,釋放內存


2. 非變動性操作

操作 效果
c.size() 返回元素個數。
c.empty() 判斷容器大小是否爲0。
c.max_size() 返回可容納元素最大數量
c1 == c2 判斷c1是否等於c2
c1 != c2 判斷c1是否不等於c2
c1 < c2 判斷c1是否小於c2
c1 > c2 判斷c1是否大於c2
c1 <= c2 判斷c1是否小於等於c2
c1 >= c2 判斷c1是否大於等於c2
c.front() 返回第一個元素,不檢查元素是否存在
c.back() 返回最後一個元素,不檢查元素是否存在
c.begin() 返回一個隨機存取迭代器,指向第一元素
c.end() 返回一個隨機存取迭代器,指向最後一個元素的下一位置
c.rbegin() 返回一個逆向迭代器,指向逆向迭代時的第一個元素
c.rend() 返回一個逆向迭代器,指向逆向迭代時最後元素的下一位置


3. 賦值操作

操作 效果
c1 = c2 將c2的全部元素賦值給c1。
c.assign(n,elem) 將elem的n個拷貝賦值給c。
c.assign(beg,end) 將區間[beg,end]的元素賦值給c
c1.swap(c2) 將c1和c2元素互換
swap(c1,c2) 同上,此爲全局函數


4. 元素存取操作

操作 效果
c.front() 返回c的第一個元素,不檢查元素存在與否
c.back() 返回c的最後一個元素,不檢查元素存在與否


5. 迭代器函數
list迭代器不支持隨機存取,這些迭代器只是雙向迭代器。

操作 效果
c.begin() 返回一個雙向迭代器,指向第一個元素
c.end() 返回一個雙迭代器,指向最後一個元素的下一位置
c.rbegin() 返回一個逆向迭代器,指向逆向迭代的第一個元素
c.rend() 返回一個逆向迭代器,指向逆向迭代的最後元素的下一位置


6. 元素的安插和移除

操作 效果
c.insert(pos,elem) 在pos位置插入一個elem副本,返回新元素的位置
c.insert(pos,n,elem) 在pos位置插入n個elem副本,無返回值
c.insert(pos,beg,end) 在pos位置插入區間[beg,end]內的元素,無返回值
c.push_back(elem) 在尾部添加一個elem的副本
c.pop_back() 移除最後一個元素,不回傳
c.push_front(elem) 在頭部插入一個elem副本
c.pop_front() 移除頭部元素,不回傳
c.remove(val) 移除所有值爲val的元素
c.remove_if(op) 移除所有造成op(elem)結果爲true的元素
c.erase(pos) 移除pos位置所指元素,返回下一元素的位置
c.erase(beg,end) 移除區間[beg,end]內的元素,返回下一元素的位置
c.resize(num) 將大小改爲num。如果size增長了,新增大小以default構造函數產生出來
c.resize(num,elem) 將大小改爲num。如果size增長了,新增大小以elem副本產生出來
c.clear() 移除所有元素,將容器清空



7. 特殊變動性操作

操作 效果
c.unique() 如果存在若干相鄰而數值相等的元素,則移除重複元素,只留下一個
c.unique(op) 如果存在若干個相鄰元素都使op()的結果爲true,則移除重複元素,只留下一個
c.splice(pos,c2) 將c2內的所有元素轉移到c1內、迭代器pos之前
c.splice(pos,c2,c2pos) 將c2內的c2pos所指元素轉移到c1內的pos所指的位置上,c1和c2可以相同
c.splice(pos,c2,c2beg,c2end) 將c2內的[c2beg,c2end]區間所有元素轉移到c1內的pos之前
c.sort() 以operator<爲準則對所有元素排序
c.sort(op) 以op()爲準則對所有元素排序
c.merge(c2) 假設c1和c2內的元素已序,將c2內的全部元素轉移到c1,保證合併後的list仍然有序
c.merge(c2,op) 假設c1和c2內的元素按照op()已序,將c2內的全部元素轉移到c1,保證合併後的list仍然在op()準則下有序
c.reverse() 將所有元素反序


8. 異常處理
所有STL標準容器中,list對於異常安全性提供了最佳支持。

操作 保證
push_back() 如果不成功,就沒有任何作用
push_front() 如果不成功,就沒有任何作用
insert() 如果不成功,就沒有任何作用
pop_back() 不拋出異常
pop_front() 不拋出異常
erase() 不拋出異常
clear() 不拋出異常
resize() 如果不成功,就沒有任何作用
remove() 只要元素比較操作不拋出異常,就不拋出異常
remove_if() 只要判斷式不拋出異常,就不拋出異常
unique() 只要元素比較操作不拋出異常,就不拋出異常
splice() 不拋出異常
merge() 只要元素比較時不拋出異常,保證“要麼不成功,要麼沒有任何作用”
reverse() 不拋出異常
swap() 不拋出異常

四、程序示例

list的使用示例

//example of list
#include <iostream>
#include <list>
#include <algorithm>
#include <iterator>
using namespace std;

void printLists(const list<int>& l1, const list<int>& l2)
{
    cout << "list1: ";
    copy(l1.begin(), l1.end(), ostream_iterator<int>(cout, " "));
    cout << endl << "list2: ";
    copy(l2.begin(), l2.end(), ostream_iterator<int>(cout, " "));
    cout << endl << endl;
}
int main()
{
    list<int> l1, l2;

    for (int i = 0; i < 6; ++i){
        l1.push_back(i);
        l2.push_front(i);
    }
    printLists(l1, l2);

    l2.splice(find(l2.begin(), l2.end(), 3), l1);
    printLists(l1, l2);

    l2.splice(l2.end(), l2, l2.begin());
    printLists(l1, l2);

    l2.sort();
    l1 = l2;

    l2.unique();
    printLists(l1, l2);

    l1.merge(l2);
    printLists(l1, l2);

    l1.reverse();
    printLists(l1,l2);

    l1.sort();
    printLists(l1,l2);
    return 0;
}

輸出結果:
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章