一、list 簡(jiǎn)介
在 C++ 中,std::list
是標(biāo)準(zhǔn)庫(kù)提供的一個(gè)容器類,用于將數(shù)據(jù)進(jìn)行鏈?zhǔn)酱鎯?chǔ)。鏈表(list)是一種物理存儲(chǔ)單元上非連續(xù)的存儲(chǔ)結(jié)構(gòu),數(shù)據(jù)元素的邏輯順序是通過鏈表中的指針鏈接實(shí)現(xiàn)的。
- 鏈表的組成:鏈表由一系列結(jié)點(diǎn)組成。
- 結(jié)點(diǎn)的組成:1.存儲(chǔ)數(shù)據(jù)元素的數(shù)據(jù)域 2.存儲(chǔ)下一個(gè)結(jié)點(diǎn)地址的指針域。
STL中的鏈表是一個(gè)雙向循環(huán)鏈表,由于鏈表的存儲(chǔ)方式并不是連續(xù)的內(nèi)存空間,因此鏈表list中的迭代器只支持前移和后移,屬于雙向迭代器。
二、std::list 與 std::vector的區(qū)別
-
底層實(shí)現(xiàn):
-
list
是由雙向鏈表實(shí)現(xiàn)的,每個(gè)元素包含指向前一個(gè)和后一個(gè)元素的指針。這種實(shí)現(xiàn)使得在列表中的任意位置插入和刪除元素都是高效的,但對(duì)于隨機(jī)訪問元素的性能較差。 -
vector
是由動(dòng)態(tài)數(shù)組實(shí)現(xiàn)的,元素在內(nèi)存中是連續(xù)存儲(chǔ)的。這種實(shí)現(xiàn)使得隨機(jī)訪問元素的性能非常好,但在中間或開頭插入/刪除元素時(shí)會(huì)涉及元素的移動(dòng),性能相對(duì)較低。
-
-
動(dòng)態(tài)調(diào)整大小:
-
list
的大小可以動(dòng)態(tài)增長(zhǎng)和縮小,因?yàn)樗褂面湵韥泶鎯?chǔ)元素,插入和刪除操作的性能與列表的大小無關(guān)。 -
vector
的大小也可以動(dòng)態(tài)增長(zhǎng),但在需要重新分配內(nèi)存時(shí),可能會(huì)導(dǎo)致大量的元素復(fù)制和內(nèi)存重分配操作。
-
-
訪問效率:
-
list
不支持隨機(jī)訪問,只能通過迭代器進(jìn)行順序訪問。對(duì)于需要頻繁插入和刪除操作的場(chǎng)景,list
的性能更好。 -
vector
支持隨機(jī)訪問,可以通過下標(biāo)直接訪問元素。對(duì)于需要頻繁的隨機(jī)訪問操作,vector
的性能更好。
-
-
內(nèi)存占用:
-
list
在存儲(chǔ)元素時(shí),除了元素本身的值外,還需要額外的空間存儲(chǔ)指向前一個(gè)和后一個(gè)元素的指針。因此,它通常比vector
使用更多的內(nèi)存。 -
vector
在存儲(chǔ)元素時(shí),只需要存儲(chǔ)元素的值本身和一些額外的控制信息,因此通常比list
使用更少的內(nèi)存。
-
-
插入和刪除操作:
-
list
對(duì)于在任意位置插入和刪除元素來說是高效的,因?yàn)樗恍枰薷南噜徳氐闹羔樇纯?,不需要移?dòng)其他元素。list
有一個(gè)重要的性質(zhì),插入操作和刪除操作都不會(huì)造成原有l(wèi)ist迭代器的失效,這在vector
中是不成立的。 -
vector
對(duì)于在末尾插入和刪除元素來說是高效的,因?yàn)樗恍枰跀?shù)組的末尾進(jìn)行操作,不需要移動(dòng)其他元素。但在中間或開頭插入/刪除元素時(shí),需要移動(dòng)其他元素。
-
綜上所述,選擇使用 list
還是 vector
取決于具體的應(yīng)用場(chǎng)景和需求。如果需要頻繁的插入和刪除操作,并且不需要頻繁的隨機(jī)訪問元素,可以選擇 list
。如果需要頻繁的隨機(jī)訪問元素,而插入和刪除操作較少,可以選擇 vector
。另外,如果需要在容器的中間位置進(jìn)行插入和刪除操作,并且對(duì)訪問效率要求不高,可以考慮使用 list
。
三、list 構(gòu)造函數(shù)
構(gòu)造函數(shù)原型 | 解釋 | |
---|---|---|
1 | list<T> lt | 默認(rèn)構(gòu)造函數(shù), 采用模板類實(shí)現(xiàn) |
2 | list(lt.begin(), lt.end()) | 將lt[begin, end)區(qū)間中的元素拷貝給本身 |
3 | list(n, Element) | 構(gòu)造函數(shù)將n個(gè)Element(元素)拷貝給本身 |
4 | list(const list <) | 拷貝構(gòu)造函數(shù) |
示例:
#include <iostream>
#include <list> //必須包含該頭文件
using namespace std;
void printVec(list<int> &v)
{
for (list<int>::iterator At = v.begin(); At != v.end(); At++)
{
cout << *At << " ";
}
cout << endl;
}
void printVec(list<double> &v)
{
for (list<double>::iterator At = v.begin(); At != v.end(); At++)
{
cout << *At << " ";
}
cout << endl;
}
void test01()
{
list<int> v1;
v1.push_back(10); //添加元素
v1.push_back(20);
printVec(v1);
list<int> v2(v1.begin(), v1.end());
printVec(v2);
list<double> v3(5, 6.32);
printVec(v3);
list<double> v4(v3);
printVec(v4);
}
int main()
{
test01();
system("pause");
return 0;
}
//result
10 20
10 20
6.32 6.32 6.32 6.32 6.32
6.32 6.32 6.32 6.32 6.32
注意:
list 作為函數(shù)的參數(shù)或者返回值時(shí),不能缺少其中的“&”。
四、list 賦值
函數(shù)原型: = 、assign | 解釋 | |
---|---|---|
1 | list& operator=(const list <) | 重載=操作符 |
2 | assign(begin, end) | 將[begin, end)區(qū)間中的數(shù)據(jù)拷貝賦值給本身 |
3 | assign(n, Element) | 將n個(gè)Element拷貝賦值給本身 |
示例:
#include <iostream>
#include <list> //必須包含該頭文件
using namespace std;
void printVec(list<int> &v)
{
for (list<int>::iterator At = v.begin(); At != v.end(); At++)
{
cout << *At << " ";
}
cout << endl;
}
void test01()
{
list<int> v1;
v1.push_back(10); //添加元素
v1.push_back(20);
printVec(v1);
list<int> v2 = v1;
printVec(v2);
list<int> v3;
v3.assign(v1.begin(), v1.end());
printVec(v3);
list<int> v4;
v4.assign(6, 1);
printVec(v4);
}
int main()
{
test01();
system("pause");
return 0;
}
//result
10 20
10 20
10 20
1 1 1 1 1 1
五、list 長(zhǎng)度操作
函數(shù)原型:empty、size、resize | 解釋 | |
---|---|---|
1 | empty() | 判斷容器是否為空 |
2 | size() | 返回容器中元素的個(gè)數(shù) |
3 | resize(int num) | 重新指定容器的長(zhǎng)度為num。若容器變長(zhǎng),則以默認(rèn)值填充新位置; 如果容器變短,則末尾超出容器長(zhǎng)度的元素被刪除 |
4 | resize(int num, Element) | 重新指定容器的長(zhǎng)度為num。若容器變長(zhǎng),則以Element值填充新位置; 如果容器變短,則末尾超出容器長(zhǎng)度的元素被刪除 |
示例:
#include <iostream>
#include <list> //必須包含該頭文件
using namespace std;
void printVec(list<int> &v)
{
for (list<int>::iterator At = v.begin(); At != v.end(); At++)
{
cout << *At << " ";
}
cout << endl;
}
void test01()
{
list<int> v1;
if (v1.empty()) //判斷是否為空
{
cout << "當(dāng)前v1為空!" << endl;
}
v1.push_back(10); //添加元素
v1.push_back(20);
v1.push_back(30);
if (!v1.empty())
{
cout << "v1中元素個(gè)數(shù):" << v1.size() << endl;
printVec(v1);
}
v1.resize(5);
printVec(v1);
v1.resize(10, 1);
printVec(v1);
}
int main()
{
test01();
system("pause");
return 0;
}
//result
當(dāng)前v1為空!
v1中元素個(gè)數(shù):3
10 20 30
10 20 30 0 0
10 20 30 0 0 1 1 1 1 1
六、list 插入與刪除
函數(shù)原型:push_back、pop_back、insert、erase、clear | 解釋 | |
---|---|---|
1 | push_back(Element) | 尾部插入元素Element |
2 | pop_back() | 刪除最后一個(gè)元素 |
3 | push_front(Element) | 在容器開頭插入一個(gè)元素 |
4 | pop_front() | 從容器開頭移除第一個(gè)元素 |
5 | insert(iterator p, Element) | 迭代器指向位置p插入元素Element |
6 | insert(iterator p, int n, Element) | 迭代器指向位置p插入n個(gè)元素Element |
7 | insert(p,iterator start, iterator end) | 在p位置插入[start,end)區(qū)間的數(shù)據(jù),無返回值 |
8 | erase(iterator p) | 刪除迭代器指向的元素 |
9 | erase(iterator start, iterator end) | 刪除迭代器從start到end之間的元素 |
10 | remove(elem) | 刪除容器中所有與elem值匹配的元素 |
11 | clear() | 刪除容器中所有元素 |
示例:
#include <iostream>
#include <list> //必須包含該頭文件
using namespace std;
void printVec(list<int> &v)
{
for (list<int>::iterator At = v.begin(); At != v.end(); At++)
{
cout << *At << " ";
}
cout << endl;
}
void test01()
{
list<int> v1;
v1.push_back(1); //尾部添加元素
v1.push_back(2);
v1.push_back(3);
v1.push_back(3);
cout << "尾部添加元素: " << endl;
printVec(v1);
v1.pop_back(); //尾部刪除元素
cout << "尾部刪除元素: " << endl;
printVec(v1);
v1.push_front(100); //頭部添加元素
v1.push_front(200);
v1.push_front(300);
cout << "頭部添加元素: " << endl;
printVec(v1);
v1.pop_front(); //頭部刪除元素
v1.pop_front();
cout << "頭部刪除元素: " << endl;
printVec(v1);
v1.insert(v1.begin(), 100); //插入元素100
cout << "插入元素100: " << endl;
printVec(v1);
v1.insert(v1.begin(), 5, 100); //插入5個(gè)元素100
cout << "插入5個(gè)元素100: " << endl;
printVec(v1);
v1.erase(v1.begin()); //刪除元素
cout << "刪除元素v1.begin(): " << endl;
printVec(v1);
v1.remove(100);
cout << "刪除所有100元素: " << endl;
printVec(v1);
v1.clear(); //清空容器
printVec(v1);
}
int main()
{
test01();
system("pause");
return 0;
}
//result
尾部添加元素:
1 2 3 3
尾部刪除元素:
1 2 3
頭部添加元素:
300 200 100 1 2 3
頭部刪除元素:
100 1 2 3
插入元素100:
100 100 1 2 3
插入5個(gè)元素100:
100 100 100 100 100 100 100 1 2 3
刪除元素v1.begin():
100 100 100 100 100 100 1 2 3
刪除所有100元素:
1 2 3
七、list 數(shù)據(jù)獲取
函數(shù)原型:front()、back | 解釋 | |
---|---|---|
1 | front() | 返回容器中第一個(gè)數(shù)據(jù)元素 |
2 | back() | 返回容器中最后一個(gè)數(shù)據(jù)元素 |
示例:
#include <iostream>
#include <list> //必須包含該頭文件
using namespace std;
void test01()
{
list<int> v1 = { 1, 2, 3, 4, 5, 6 };
cout << "v1.front() = " << v1.front() << endl;
cout << "v1.back() = " << v1.back() << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
//result
v1.front() = 1
v1.back() = 6
八、list 互換、反轉(zhuǎn)、排序
函數(shù)原型:swap、reverse、sort | 解釋 | |
---|---|---|
1 | swap(list lt) | 將lt中元素與本身的元素互換 |
2 | reverse() | 反轉(zhuǎn)鏈表 |
3 | sort() | 鏈表排序 |
示例:文章來源:http://www.zghlxwxcb.cn/news/detail-741854.html
#include <iostream>
#include <list> //必須包含該頭文件
using namespace std;
void printVec(list<int> &v)
{
for (list<int>::iterator At = v.begin(); At != v.end(); At++)
{
cout << *At << " ";
}
cout << endl;
}
void test01()
{
list<int> v1 = { 9, 5, 7, 8, 6 };
list<int> v2 = { 5, 4, 3, 2, 1 };
v1.swap(v2); //互換v1與v2中的元素
cout << "list v1 : " ;
printVec(v1);
cout << "list v2 : " ;
printVec(v2);
v2.sort(); //鏈表排序
cout << "v2鏈表排序 : ";
printVec(v2);
v2.reverse(); //反轉(zhuǎn)鏈表v2
cout << "v2反轉(zhuǎn)鏈表 : ";
printVec(v2);
}
int main()
{
test01();
system("pause");
return 0;
}
//result
list v1 : 5 4 3 2 1
list v2 : 9 5 7 8 6
v2鏈表排序 : 5 6 7 8 9
v2反轉(zhuǎn)鏈表 : 9 8 7 6 5
如果這篇文章對(duì)你有所幫助,渴望獲得你的一個(gè)點(diǎn)贊!
文章來源地址http://www.zghlxwxcb.cn/news/detail-741854.html
到了這里,關(guān)于【C++】鏈表(list)的使用以及與vector的區(qū)別的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!