淺談C++ 容器查找效率
只要選對(duì)容器,多寫幾行代碼就能讓程序“飛”起來。下面用生活化的比喻 + 足夠多的帶注釋示例,幫你弄懂常用 STL 容器的查找特性。
讀完你應(yīng)該能快速判斷:“我的場(chǎng)景該用哪一個(gè)?”
0. 先把“查找復(fù)雜度”聊明白
記號(hào) | 含義 | 舉個(gè)?? |
---|---|---|
O(1) | 常數(shù)時(shí)間 | 像從冰箱門口拿飲料——一下就到手 |
O(log n) | 對(duì)數(shù)時(shí)間 | 折半查電話簿——越找越快 |
O(n) | 線性時(shí)間 | 排隊(duì)買奶茶——要挨個(gè)等 |
只要記?。簲?shù)字越小越快,O(1)
最爽,O(n)
最慢。
1. std::vector —— “排排坐”的長(zhǎng)桌子
特點(diǎn):元素一字排開,內(nèi)存連續(xù),跟操場(chǎng)跑道一樣直。
查找
- 沒排序:只能一個(gè)個(gè)比——
O(n)
- 排好序:可折半查——
O(log n)
#include <vector> #include <algorithm> // std::sort, std::binary_search #include <iostream> int main() { std::vector<int> nums{5, 1, 4, 3, 2}; // 連續(xù)擺放的「長(zhǎng)桌子」 std::sort(nums.begin(), nums.end()); // ① 排序一次,之后查找快 // nums 變成 {1,2,3,4,5} bool has3 = std::binary_search( // ② 折半查找 3 nums.begin(), nums.end(), 3); // O(log n) std::cout << (has3 ? "找到了" : "沒找到") << '\n'; }
什么時(shí)候用
- 數(shù)據(jù)量可控、想要下標(biāo)隨機(jī)訪問。
- 插入刪除不多(尤其不是在中間插)。
2. std::list —— “珍珠項(xiàng)鏈”
- 特點(diǎn):每顆珠子(節(jié)點(diǎn))用線(指針)串起來,插拔容易。
- 查找:得一顆顆摸——
O(n)
,而且分散指針不利于 CPU 緩存。
#include <list> #include <algorithm> #include <iostream> int main() { std::list<int> lst{1, 2, 3, 4, 5}; // 一串節(jié)點(diǎn) auto it = std::find(lst.begin(), lst.end(), 3); // ① 線性查找 std::cout << (it != lst.end() ? "找到了" : "沒找到") << '\n'; }
什么時(shí)候用插入 / 刪除動(dòng)作特別頻繁、但不太在意查找速度,比如任務(wù)隊(duì)列需要隨時(shí)插入或移走元素。
3. std::set —— 自動(dòng)排序的“有序字典”
- 底層:紅黑樹,像一個(gè)能自動(dòng)平衡的家譜圖。
- 查找 / 增刪:都 O(log n)。
#include <set> #include <iostream> int main() { std::set<int> s{4, 1, 3, 2}; // 元素自動(dòng)有序:{1,2,3,4} bool has2 = s.contains(2); // C++20 起可直接 contains std::cout << (has2 ? "有 2" : "沒 2") << '\n'; }
什么時(shí)候用既想要“去重”又想要“元素排好序”,而且單個(gè)元素查找要快。
4. std::unordered_set —— “散列表”小黑屋
- 底層:哈希表,把元素按哈希值分到不同“桶”里。
- 平均查找:O(1),最壞沖突多時(shí) O(n)。
- 元素?zé)o序:放進(jìn)去啥順序不管。
#include <unordered_set> #include <iostream> int main() { std::unordered_set<std::string> words; // 小黑屋摞桶 words.insert("hello"); words.insert("world"); if (words.contains("hello")) { // 平均 O(1) std::cout << "嘿~ 找到了 hello\n"; } }
什么時(shí)候用不需要順序,只想“秒查秒存”,典型如去重、統(tǒng)計(jì)次數(shù)。
5. std::map vs std::unordered_map —— 鍵值對(duì)“雙子星”
容器 | 底層 | 查找 | 是否有序 |
---|---|---|---|
map | 紅黑樹 | O(log n) | ? |
unordered_map | 哈希表 | O(1) 平均 | ? |
#include <map> #include <unordered_map> #include <iostream> int main() { std::map<int, std::string> ordered; // 有序 ordered[2] = "B"; ordered[1] = "A"; std::unordered_map<int, std::string> hash; // 無序 hash[2] = "B"; hash[1] = "A"; std::cout << ordered[1] << ' ' << hash[1] << '\n'; }
什么時(shí)候用
- 需要按鍵遍歷且保持有序:
map
。 - 只關(guān)心查、增、刪速度:
unordered_map
。
6. std::deque —— 可以從兩頭裝菜的“長(zhǎng)盤子”
- 特點(diǎn):首尾插入 / 刪除都是 O(1);中間操作比 vector 慢點(diǎn)。
- 查找:線性 O(n);隨機(jī)訪問語(yǔ)法與 vector 一樣。
#include <deque> #include <algorithm> #include <iostream> int main() { std::deque<int> q{1, 2, 3}; q.push_front(0); // 頭部 O(1) q.push_back(4); // 尾部 O(1) bool has3 = std::find(q.begin(), q.end(), 3) != q.end(); std::cout << (has3 ? "有 3" : "沒 3") << '\n'; }
什么時(shí)候用既想要隨機(jī)訪問,又要在首尾頻繁加減元素,比如滑動(dòng)窗口算法。
7. “多索引”技巧 —— 一份數(shù)據(jù),多把鑰匙
如果你既想按 ID 查,又想按 名字 查,可以:
#include <vector> #include <unordered_map> struct User { int id; std::string name; }; std::vector<User> users; // 主數(shù)組 std::unordered_map<int, User*> id_index; // id → 指針 std::unordered_map<std::string, User*> name_index; // name → 指針
- 插入一個(gè)用戶時(shí),三處都要更新。
- 查找時(shí),從對(duì)應(yīng)索引直接拿到指針,速度飛快。
8. 記憶卡片(純中文朗朗上口)
小而隨機(jī)選 vector
插刪中間選 list
要有序就 set/map
求極致快 unordered_*
兩頭忙活用 deque
多條件查 自建索引
最后一句話
先寫代碼,測(cè)一次性能——復(fù)雜度只給方向,真快還是得跑數(shù)據(jù)。祝你寫得順、跑得飛!
到此這篇關(guān)于淺談C++ 容器查找效率的文章就介紹到這了,更多相關(guān)C++ 容器查找效率內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++聚合關(guān)系類的構(gòu)造函數(shù)的調(diào)用順序詳解
下面小編就為大家?guī)硪黄狢++聚合關(guān)系類的構(gòu)造函數(shù)的調(diào)用順序詳解。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考,一起跟隨小編過來看看吧2016-05-05C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之圖書借閱系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之圖書借閱系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03C++中實(shí)現(xiàn)線程安全和延遲執(zhí)行詳解
這篇文章主要為大家詳細(xì)介紹了C++中實(shí)現(xiàn)線程安全和延遲執(zhí)行的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的小伙伴可以了解下2024-01-01