文章目錄
- 😘 閑聊幾句
- 👍 list
- 👍list的反轉和排序
- 👍set/multiset
- 👍對組
- 👍map / multimap
- ??最后
😘 閑聊幾句
時間過的很快,碼神馬上就要開學了,這也是STL系列的最后一篇了,假期學了不少,距離自己的奧賽巔峰水平可以說是十分接近了,如果說學這c++有什么用的話,可能就是興趣所至吧,在博客更新之際,也認識了不少行業大佬,給我提了不少意見,感謝!STL完了以后,就是演算法和python腳本吧,做自己想做的事情,更要做難的事情,總體來說STL的瀏覽量不多,但是還要說,why?因為有些演算法題,你適當的使用STL,用過的都知道👍,所以我還是堅持將STL講完了、
那就這么多,開始吧:
- list ——鏈表
- set ——關聯式容器,底層是由二叉樹實作的
- map容器
👍 list
對資料結構中鏈表陌生的兄弟們,可以看下我的碼神爆肝5w字資料結構,記得我說過一句話,陣列的缺點就是鏈表的優點,鏈表的缺點就是鏈表的優點,還記得陣列的優點是什么?陣列的優點是:可以隨機訪問,缺點是:插入和洗掉要移動所有元素,同樣可以類比出鏈表的優缺點,
STL中的鏈表略有不同,是STL中鏈表是雙向鏈表

和vector的操作基本一致,比較不同的是在洗掉操作時多了個remove(c):洗掉與c一樣的資料,開車了
#include<iostream>
#include<list>
using namespace std;
void print(list<int> &l)
{
for (list<int> ::iterator it = l.begin(); it != l.end(); it++)
{
cout << *it<<" ";
}
cout << endl;
}
void test01()
{
list<int> l;
l.push_back(10);
l.push_back(20);
l.push_front(100);
l.push_front(200);
if (l.empty())
{
cout << "為空";
}
else
{
cout<<l.size()<<endl;
}
print(l);
//200 100 10 20
l.pop_back();
print(l);
//200 100 10
l.clear();
}
int main()
{
test01();
return 0;
}
這里對比,vector值得注意的是list是鏈式存盤,所以在迭代器iterator中出現,it+1,等操作,取而代之的是it++,一個一個走
用專業方式就是說,支持it+1,是支持隨機訪問,反之就是不支持隨機訪問不能用at和【】
👍list的反轉和排序
這個我感徑訓是有點用的,所以單獨說一下,
先來說反轉:reverse函式
排序:有個algorithm中的sort不知道還記得不?但是有個前提是,sort只適用在隨機訪問的資料結構中,list為了方便引入了專門的sort,使用方法是l.sort(),
下面我們用代碼來實作一下,這倆個功能
#include<iostream>
#include<algorithm>
#include<list>
using namespace std;
void print(list<int> &L)//列印
{
for (list<int> ::iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
bool fanzhuan(int v1,int v2)
{
return v1 > v2;
}
void test01()
{
list<int> l1;
l1.push_back(10);
l1.push_back(20);
l1.push_back(30);
l1.push_back(20);
l1.push_back(10);
print(l1);
l1.reverse();
print(l1);
//從小到大排
l1.sort();
print(l1);
//從大到小
l1.reverse();
print(l1);
//換一個方式
l1.push_front(10);
l1.sort(fanzhuan);
print(l1);
}
int main()
{
test01();
return 0;
}
可以看到我在實作從大到小時,使用了倆個方法,我們為什么不直接反轉呢?原因還是從效率上考慮的,首先我們要明白反轉的本質是:
初始化一個為 null 的 previous node(prev),然后遍歷鏈表的同時,當前 node (curr)的下一個(next)指向前一個 node(prev), 在改變當前 node 的指向之前,用一個臨時變數記錄當前 node 的下一個 node. 即

可以看出時間效率有點低,所以用bool變數寫了個函式,來實作從小到大的排序,
👍set/multiset
所有元素都會在插入時自動被排序這應該是它最主要的特定了!
這兩個是屬于關聯式容器,其底層架構是由二叉樹實作的,那么如果沒有區別,肯定是不行的,要不然直接用一個不就好了嘛,看區別:
- set不允許有重復元素
- multiset允許有重復元素
看一下set的基本操作:
- empty
- size
- swap——交換倆個集合
- insert——插入
- erase——洗掉
- 清空:erase(s.benin(),s.end())
- clear()
- find—查找
- 存在回傳s的迭代器,不存在回傳s.end()
- count(key)——統計key的個數
//set是一個容器,區別是當他剛插入是就已經排好了,集合
#include<set>
#include<iostream>
using namespace std;
void print(set<int> &s)
{
for (set<int> ::iterator it = s.begin(); it != s.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
set<int>s1;
s1.insert(10);
s1.insert(20);
s1.insert(5);
s1.insert(1);
set<int>s2;
s2.insert(44);
s2.insert(11);
s2.insert(55);
print(s2);
print(s1);
//交換
s1.swap(s2);
print(s2);
print(s1);
cout<<s1.cout(11);
//應該是1,因為s1和s2互換了序列
int num=s1.count(10);
cout<<num<<endl;
應該為0
cout << s1.size() << " " << s2.size();
}
int main()
{
test01();
return 0;
}
multiset,下來我們來驗證一下,前面說過這個容器允許重復插入,這個頭檔案仍然使用set
下面我們用仿函式來改變set的排序,讓它從大到小來進行排序
#include<iostream>
#include<set>
#include<algorithm>
using namespace std;
//仿函式
class compare
{
public:
bool operator()(int l1,int l2)
{
return l1 > l2;
}
};
void print(set<int> &s)
{
for (set<int> ::iterator it = s.begin(); it != s.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
set<int> s;
s.insert(30);
s.insert(20);
s.insert(40);
s.insert(50);
s.insert(10);
print(s);
//排序
set<int, compare>s1;
s1.insert(30);
s1.insert(20);
s1.insert(40);
s1.insert(50);
s1.insert(10);
//print(s1);
for (set<int, compare>::iterator it = s1.begin(); it != s1.end(); it++)
{
cout << *it << " ";
}
}
int main()
{
test01();
return 0;
}
👍對組
聽名字來看,應該是成對出現的,所以叫對組,比較簡單
#include<iostream>
#include<string>
using namespace std;
void test01()
{
pair<string, int> p(string("masheng"), 20);
cout << p.first << " " << p.second << endl;
pair<string, int>p1("tom", 18);
cout << p1.first << " " << p1.second << endl;
}
int main()
{
test01();
return 0;
}
這里我們運用到了pair關鍵字,對
👍map / multimap
也是使用頻率比較高的容器,由于它的性能高,效率高,其底層是由紅黑樹實作的,但是如果展開來講紅黑樹的話,太長了,所以我們,直接來看這個容器,值得注意的一點是:這個容器的每一個元素都是pair,上會講到的對組,其中對組的第一個元素為key(鍵值),后一個元素為value(實值),
這倆個容器的區別有點像set
map中不允許有重復的key值元素
multimap允許有重復的key值元素
都有的特點有:
- 所有的元素都自動排列
- 可以根據key值快速找到value值
#include<map>
#include<iostream>
using namespace std;
void print(map<int,int> &m1)
{
for (map<int,int> ::iterator it=m1.begin();it!=m1.end();it++)
{
cout << it->first << " " << it->second;
}
cout << endl;
}
void test01()
{
map<int, int> m;
//用pair傳入
m.insert(pair<int, int>(1, 5));
m.insert(pair<int, int>(8, 5));
m.insert(pair<int, int>(3, 5));
//可以看出根據key值來排序
map<int, int>m1(m);
m1 = m;
print(m);
}
int main()
{
test01();
return 0;
}
和其他容器一樣,我們看幾個函式
- size——大小
- empty——是否為空
- swap——交換集合
- insert——之前用到過的插入
- clear——清空
- erase——洗掉
- find——查找到了回傳迭代器,查找不到回傳end
- count——通上也是統計
值得注意的是map的用【】插入,查找的功能
在用【】查找時,如果查找的資料沒有,那么編譯器會自動賦值一個資料給到map容器,插入時,value值為0,key值為所查找的值
m[5]=10;,假如5沒有,那么5對應的value就為10,或者是這樣m【5】;這樣5對應0
還有插入:m.insert(make_pair(5,20))和上面的m.insert(<int,int>5,20)
都是比較常用的,但是我不建議在插入時使用【】
void test01()
{
map<int, int>m;
m[5];
print(m);
}
??最后
碼神的開車之旅STL車型也算是圓滿結束了,不知道你怎么樣?關鍵是去找各個容器的相同點和不同點來進行對比的記憶,不知道你們有沒有看到,就是在學了幾個容器后,發現都是大同小異,不難,對吧?底層都是寫好的,應用都是靠自己了,在更新完stl后,我也是要休息幾天準備下大學生活了,感謝支持,停幾天,給大家更新,還是老樣子:
如果覺得文章對你有幫助,🎉歡迎關注🔎點贊👍收藏??留言📝,一鍵四連支持,你的支持就是我創作最大的動力,
💌 歡迎大家在評論區提出意見和建議!💌
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/300473.html
標籤:其他
