做網(wǎng)站開發(fā)人員架構(gòu)市場營銷
文檔介紹
文檔介紹
1.list是可以在常數(shù)范圍內(nèi)的任意位置進(jìn)行插入和刪除的序列式容器,并且該容器可以前后雙向迭代
2.list的底層是帶頭雙向鏈表循環(huán)結(jié)構(gòu),雙向鏈表中每個元素存儲在互不相關(guān)的獨立節(jié)點中,在節(jié)點中通過指針指向其前一個元素和后一個元素
3.list和forward_list非常相似,最主要的不同在于forward_list是單鏈表,只能朝前迭代,已讓其更簡單高效
4.與其他的序列式容器相比(array,vector,deque),list通常在任意位置進(jìn)行插入、移除元素的執(zhí)行效率更好
5.與其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的隨機訪問,比如:要訪問list的第6個元素,必須從已知的位置(比如頭部或者尾部)迭代到該位置,在這段位置上迭代需要線性的時間開銷,list還需要一些額外的空間,以保存每個節(jié)點的相關(guān)聯(lián)信息(對于存儲類型較小元素的大list來說這可能是一個重要的因素)
注意事項
1.list沒有擴(kuò)容的方法
2.list不支持[]訪問,不是連續(xù)存儲的
3.remove移除元素,有則刪除,沒有不報錯
4.splice粘接,轉(zhuǎn)移元素
5.迭代器的分類
(1) 單向迭代器 ,++,如單鏈表
(2) 雙向迭代器,++,–如list
(3) 隨機迭代器,++,–,+,-,如vector
下面的包含上面迭代器的功能
下圖是list的迭代器
6.鏈表為什么自己實現(xiàn)了sort,不像vector一樣用算法庫的sort。因為算法庫的sort用的是快速排序,里面的三數(shù)取中對于鏈表不能用,且sort的參數(shù)也有提示
sort需要傳的是隨機迭代器,而鏈表的是雙向迭代器,理論上模板可以傳任意參數(shù),但內(nèi)部使用迭代器有要求
7.list的sort效率不太高,100萬數(shù)據(jù)和vector差了4倍
使用
構(gòu)造
構(gòu)造函數(shù) constructor | 接口說明 |
---|---|
list (suze_type n, const value_type& val = value_type()) | 構(gòu)造的list中包含n個值為val的元素 |
list () | 構(gòu)造空的list |
list (const list& x) | 構(gòu)造拷貝函數(shù) |
list (InputIterator first, InputIterator last) | 用(first, last)區(qū)間中的元素構(gòu)造list |
list<int> l1; // 構(gòu)造空的l1list<int> l2(4, 100); // l2中放4個值為100的元素list<int> l3(l2.begin(), l2.end()); // 用l2的[begin(), end())左閉右開的區(qū)間構(gòu)造l3list<int> l4(l3); // 用l3拷貝構(gòu)造l4// 以數(shù)組為迭代器區(qū)間構(gòu)造l5int array[] = { 16,2,77,29 };list<int> l5(array, array + sizeof(array) / sizeof(int));// 列表格式初始化C++11list<int> l6{ 1,2,3,4,5 };
迭代器
迭代器理解成一個指針,指向list中某個節(jié)點
函數(shù)聲明 | 接口說明 |
---|---|
begin + end | 返回第一個元素的迭代器 + 返回最后一個元素下一個位置的迭代器 |
rbegin + rend | 返回第一個元素的reverse_iterator,即end位置,返回最后一個元素下一個位置的reverse_iterator,即begin的位置 |
begin和end為正向迭代器,對迭代器執(zhí)行++操作,迭代器向后移動
rbegin和rend為反向迭代器,++操作,向前移動
// 用迭代器方式打印l5中的元素list<int>::iterator it = l5.begin();while (it != l5.end()){cout << *it << " ";++it;} cout << endl;// C++11范圍for的方式遍歷for (auto& e : l5)cout << e << " ";cout << endl;
}
// list迭代器的使用
// 注意:遍歷鏈表只能用迭代器和范圍for
void PrintList(const list<int>& l)
{// 注意這里調(diào)用的是list的 begin() const,返回list的const_iterator對象for (list<int>::const_iterator it = l.begin(); it != l.end(); ++it){cout << *it << " ";// *it = 10; 編譯不通過}cout << endl;
}void TestList2()
{int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };list<int> l(array, array + sizeof(array) / sizeof(array[0]));// 使用正向迭代器正向list中的元素// list<int>::iterator it = l.begin(); // C++98中語法auto it = l.begin(); // C++11之后推薦寫法while (it != l.end()){cout << *it << " ";++it;}cout << endl;// 使用反向迭代器逆向打印list中的元素// list<int>::reverse_iterator rit = l.rbegin();auto rit = l.rbegin();while (rit != l.rend()){cout << *rit << " ";++rit;}cout << endl;
}
容量
函數(shù)聲明 | 接口說明 |
---|---|
empty | 檢測list是否為空,返回true,否則返回false |
size | 返回list中有效節(jié)點的個數(shù) |
front | 返回list的第一個節(jié)點中值的引用 |
back | 返回list的最后一個節(jié)點中值的引用 |
修改
函數(shù)聲明 | 接口說明 |
---|---|
push_front | 在list首元素前插入值為val的元素 |
pop_front | 刪除list中第一個元素 |
push_back | 在list尾部插入值為val的元素 |
pop_back | 刪除list中最后一個元素 |
insert | 在list position位置中插入值為val的元素 |
erase | 刪除lsit position位置的元素 |
swap | 交換兩個lsit的元素 |
clear | 清空list的有效元素 |
// list插入和刪除
// push_back/pop_back/push_front/pop_front
void TestList3()
{int array[] = { 1, 2, 3 };list<int> L(array, array + sizeof(array) / sizeof(array[0]));// 在list的尾部插入4,頭部插入0L.push_back(4);L.push_front(0);PrintList(L);// 刪除list尾部節(jié)點和頭部節(jié)點L.pop_back();L.pop_front();PrintList(L);
}// insert /erase
void TestList4()
{int array1[] = { 1, 2, 3 };list<int> L(array1, array1 + sizeof(array1) / sizeof(array1[0]));// 獲取鏈表中第二個節(jié)點auto pos = ++L.begin();cout << *pos << endl;// 在pos前插入值為4的元素L.insert(pos, 4);PrintList(L);// 在pos前插入5個值為5的元素L.insert(pos, 5, 5);PrintList(L);// 在pos前插入[v.begin(), v.end)區(qū)間中的元素vector<int> v{ 7, 8, 9 };L.insert(pos, v.begin(), v.end());PrintList(L);// 刪除pos位置上的元素L.erase(pos);PrintList(L);// 刪除list中[begin, end)區(qū)間中的元素,即刪除list中的所有元素L.erase(L.begin(), L.end());PrintList(L);
}
迭代器失效
前面說過此處大家可將迭代器暫時理解成指針,迭代器失效即迭代器所指向的節(jié)點無效,該節(jié)點被刪除了,因為list的底層結(jié)構(gòu)為帶頭節(jié)點的雙向循環(huán)鏈表,因此在list中插入時不會導(dǎo)致list的迭代器失效,只有刪除才會,并且失效的只是指向被刪除節(jié)點的迭代器,其他迭代器不會受影響
void TestListIterator1()
{int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };list<int> l(array, array+sizeof(array)/sizeof(array[0]));auto it = l.begin();while (it != l.end()){// erase()函數(shù)執(zhí)行后,it所指向的節(jié)點已被刪除,因此it無效,在下一次使用it時,必須先給
其賦值l.erase(it); ++it;}
}
// 改正
void TestListIterator()
{int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };list<int> l(array, array+sizeof(array)/sizeof(array[0]));auto it = l.begin();while (it != l.end()){l.erase(it++); // it = l.erase(it);}
}