注:原創不易,轉載請務必注明原作者和出處,感謝支持!
注:內容來自某培訓課程,不一定完全正確!
一 list容器
鏈表list是一種物理存儲單元上非連續,非順序的存儲結構,數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現的。鏈表由一系列結點(鏈表中每一個元素稱為結點)組成,結點可以在運行時動態生成。每個結點包括兩個部分:一個是存儲數據元素的數據域,另一個是存儲下一個結點地址的指針域。(熟悉的鏈表的味道)
list特性總結:
(1) 采用動態存儲分配,不會造成內存浪費和溢出
(2)鏈表執行插入和刪除十分方便,修改指針即可,不需要移動大量元素
(3)鏈表靈活,但是空間和時間額外耗費比較大
如圖所示,C++中list實際上更像是雙向鏈表。它所支持的常用操作也在圖中列出。
鏈表和數組有什么區別?
(1)數組必須事先定義固定長度(元素個數),不能適應數據動態地增減的情況。當數據增加時,可能超出原先定義的元素個數;當數據減少時,造成內存浪費。
(2)鏈表動態地進行存儲分配,可以適應數據動態地增減的情況,且可以方便地插入,刪除數據元素。在數組中插入,刪除數據項時,需要移動其它數據項。
1.1 list常用API
構造函數
list<T> lst; // 對象的默認構造形式
list(beg, end); // 將[beg, end)區間中的元素拷貝給本身
list(n, elem); // 將n個elem元素拷貝給本身
list(const list &lst); // 拷貝構造函數
插入和刪除
push_back(elem); // 尾部插入元素
pop_back(); // 尾部刪除元素
push_front(); // 首部插入元素
pop_front(); // 首部刪除元素
insert(pos, elem); // 在pos位置插入elem元素,返回數據的位置
insert(pos, n, elem); // 在pos位置插入n個elem元素,無返回值
insert(pos, beg, end); // 在pos位置插入區間[beg, end)的元素,無返回值
clear(); // 清空容器
erase(beg, end); // 刪除[beg, end)區間內的數據
erase(pos); // 刪除pos位置的數據,返回下一個數據的位置
remove(elem); // 刪除容器中所有與elem匹配的元素
大小操作
size(); // 返回容器中元素個數
empty(); // 判斷容器是否為空
resize(num); // 重新指定容器的長度為num,若容器變長,則以默認值填充。如果容器變短,則超出容器長度元素將被刪除
resize(num, elem); // 重新指定容器長度為num,elem為填充的默認值
賦值操作
assign(beg, end); // 將[beg, end)區間中的數據拷貝賦值給本身
assign(n, elem); // 將n個elem拷貝賦值給本身
// 重載等號運算符
list &operator=(const list &lst);
swap(lst); // 將lst與本身的元素互換
數據存取
front(); // 返回第一個元素
back(); // 返回最后一個元素
逆序和排序
reverse(); // 反轉鏈表
sort(); // 排序
1.2 list應用案例
void printList(list<int> &l)
{
for (list<int>::iterator it = l.begin(); it != l.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
}
// 初始化
void Test1()
{
list<int> lst1;
list<int> lst2(10, 10);
list<int> lst3(lst2.begin(), lst2.end());
list<int> lst4(lst3);
printList(lst4);
}
// 插入和刪除
void Test2()
{
list<int> lst;
lst.push_back(100);
lst.push_front(200);
lst.insert(lst.begin(), 500);
lst.insert(lst.end(), -100);
list<int>::iterator pos = lst.begin();
pos++;
pos++;
// 在lst.begin() + 2的位置前插入2個10
lst.insert(pos, 2, 10);
printList(lst);
pos = lst.begin();
int arr[] = { 1, 2, 3, 4, 5 };
pos++; pos++; pos++; pos++;
lst.insert(pos, arr, arr + sizeof(arr) / sizeof(int));
printList(lst);
// 刪除
lst.pop_back();
lst.pop_front();
printList(lst);
lst.remove(10);
printList(lst);
lst.erase(lst.begin(), lst.end());
if (lst.empty())
{
cout << "list is empty !" << endl;
}
}
// 賦值
void Test3()
{
list<int> l;
l.assign(10, 10);
list<int> l2;
l2 = l;
printList(l2);
}
// 從大到小排序
bool cmp(int a, int b)
{
return a > b;
}
// 逆序和排序
void Test4()
{
int arr[] = { 1, 4, 9, 5, 8, 2, 7 };
list<int> l(arr, arr + sizeof(arr) / sizeof(int));
printList(l);
l.reverse();
printList(l);
// 這里的sort()是list的成員函數不是alogrithm里的算法
l.sort(cmp);
printList(l);
}
注意:算法algorithm頭文件中的sort()算法只支持可隨機訪問的容器,而list是不支持隨機訪問的,所以list自己提供了sort()成員方法。