學好這 13 種數(shù)據(jù)結(jié)構(gòu),應(yīng)對各種編程語言(C++ 版)

學了這么長時間數(shù)據(jù)結(jié)構(gòu)和算法池充,有必要來個總結(jié)了桩引,順便回顧一下我們這段時間的學習成果。以 C++ 語言本身提供的數(shù)據(jù)結(jié)構(gòu)為例收夸。如果能掌握這 13 種數(shù)據(jù)結(jié)構(gòu)坑匠,相信在學習其它語言的時候就不費勁了。?

數(shù)組 Array?

看我主頁簡介免費C++學習資源咱圆,視頻教程笛辟、職業(yè)規(guī)劃、面試詳解序苏、學習路線手幢、開發(fā)工具

每晚8點直播講解C++編程技術(shù)。

數(shù)組在初始化的時候就需要知道其大小忱详,后續(xù)是不可以改變其大小的围来,可以通過下標來獲取某個 index 中存放的元素。在 C++ 中通過源碼可以知道匈睁,它其實是在 C 數(shù)組的基礎(chǔ)上封裝的:?

#include?<array>

void?testArray()?{

// 創(chuàng)建一個數(shù)組

std::array a = {2,?4,?6,?8,?10};

// 對數(shù)組進行遍歷

for?(const?auto?i : a) {

std::cout?<< i <<?std::endl;

}

for(int?i =?0; i < a.size(); i++) {

std::cout?<< a[i] <<?std::endl;

}

// 取第一個值监透,通過 [index] 獲取

std::cout?<<?"a[0] = "?<< a[0] <<?std::endl;

// 修改數(shù)組中第一個值

a[0] =?5;

/**

at 會檢查 index 是否越界,越界將 crash航唆,而 a[index] 不會;

libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: array::at

*/

a.at(0);

// 數(shù)組是否為空

a.empty();

// 求數(shù)組的長度

std::cout?<<?"a.size()="?<< a.size() <<?std::endl;

// 獲取第4個值

int?value =?std::get<4>(a);

std::cout?<<?"a(4) = "?<< value <<?std::endl;

// 創(chuàng)建一個空數(shù)組胀蛮,數(shù)組中的值為0或者是與類型相等的其它值

std::array a2;

std::cout?<<?"end a2"?<< a2[0] <<?std::endl;

// 比較兩個數(shù)組中的元素是否都相等

if?(a == a2) {}

}

可變數(shù)組,向量vector

在C++中使用 Vector 存當可變數(shù)組,它的容量可以動態(tài)改變糯钙,初始化的時候不需要確定數(shù)組的大小粪狼。使用的方法和數(shù)組基本一致。

#include?<vector>

// 向量

void?testVector()?{

/**

vector<T> 它與Array不同任岸,它的大小是可變的

*/

std::vector v;

// 增加容器的容量再榄,至少容納 20 個元素

v.reserve(20);

// 初始化一個向量

std::vector v2 = {2,?4,?5,?7};

// 以數(shù)組初始化一個vector

std::array words {"one",?"two","three",?"four",?"five"};

std::vector words_copy {std::begin(words) ,?std::end(words)};

// 通過 v[index] 獲取或者修改元素

std::cout?<<?"v[0] = "?<< v2[1] <<?std::endl;

// 獲取第一個元素

std::cout?<<?"v.front() = "?<< v2.front() <<?std::endl;

// 在末尾插入值為 9

v2.push_back(9);

// 在末尾插入值為 2

v2.emplace_back(2);

// 刪除第一個元素,傳入的值是一個迭代器

v2.erase(v2.begin());

// 長度

v2.size();

// 刪除所有元素

v2.clear();

// 刪除末尾元素

v2.pop_back();

// 在末尾插入元素

v2.insert(v2.end(),?3);

}

雙向鏈表 list?

雙向鏈表具有指向前一個節(jié)點和后一個節(jié)點的指針享潜。C++ 中本身提供了雙向鏈表的實現(xiàn)困鸥。

#include?<list>

void?testList()?{

list words {"hello",?"list"};

// 頭部插入元素

words.push_front("push_fron");

words.emplace_front("emplace_front");

// 尾部插入

words.push_back("push_back");

words.emplace_back("emplace_back");

// 指定位置插入

words.insert(words.begin()++,?"insert");

// 刪除元素

words.remove("push_fron");

// 通過迭代器來訪問鏈表中的元素

list::iterator beg_iter = words.begin();

list::iterator end_iter = words.end();

cout?<<?"beg_iter:"?<< *beg_iter <<?endl;

cout?<<?"end_iter:"?<< *end_iter <<?endl;

for?(auto?a : words) {

cout?<< a <<?endl;

}

}

單鏈表 forward_list?

單鏈表只有指向下一個節(jié)點的指針,前面關(guān)于單鏈表我們做了好多算法題剑按。

#include?<forward_list>

void?testForwardList()?{

forward_list flist {"name",?"lefe",?"hello"};

// 計算它的大小

auto?count = distance(begin(flist), end(flist));

cout?<<?"size:"?<< count <<?endl;

// 頭部插入

flist.push_front("before3");

// 在頭部插入

flist.insert_after(flist.begin(),?"before2");

// 在頭結(jié)點前面插入

flist.insert_after(flist.before_begin(),?"before1");

// 遍歷單鏈表

for?(auto?word : flist) {

cout?<< word <<?endl;

}

}

隊列 queue

隊列是一種先進先出的數(shù)據(jù)結(jié)構(gòu)疾就,C++底層使用「雙端隊列」實現(xiàn)。關(guān)于隊列的更多內(nèi)容吕座,可以看這篇內(nèi)容?圖解設(shè)計一個循環(huán)隊列虐译。

#include?<queue>

void?testQueue()?{

queue s;

// 入隊

s.push(1);

// 出隊

s.pop();

// 隊首

s.front();

// 隊尾

s.back();

// 隊大小

s.size();

}

雙端隊列deque

雙端隊列可以對隊頭和隊尾元素進行操作。在做算法的時候我們設(shè)計過一個雙端隊列圖解設(shè)計一個雙端隊列吴趴。?

void?testDeque()?{

// 初始化一個空雙端隊列

deque my_deque;

// 初始化一個含有兩個元素雙端隊列

deque name_queue {"lefe",?"wsy"};

cout?<<?"[0] = "?<< name_queue[0] <<?endl;

// 獲取隊頭元素

cout?<<?"front = "?<< name_queue.front() <<?endl;

// 獲取隊尾元素

cout?<<?"back = "?<< name_queue.back() <<?endl;

// 從尾部入隊

name_queue.push_back("bx");

name_queue.pop_front();

}

優(yōu)先隊列 priority_queue

優(yōu)先隊列和普通隊列一樣只能在隊尾插入元素漆诽,隊頭刪除元素,但是它有一個特點锣枝,隊頭永遠是優(yōu)先級最大的元素厢拭,出隊順序與入隊順序無關(guān)。C++ 中的底層使用「堆」實現(xiàn)的撇叁,這樣時間復(fù)雜度可以控制在 O(logn)供鸠。

void?testPriorityQueue()?{

// 創(chuàng)建優(yōu)先隊列

priority_queue q;

// 向隊列中添加元素

q.push(4);

q.push(1);

for(int?i =?0?; i < q.size() ; i++) {

cout?<< q.top() <<?endl;

// 刪除第一個元素

q.pop();

}

// 隊列是否為空

q.empty();

}

堆heap

堆是一顆完全二叉樹,某個節(jié)點的值總是不大于父節(jié)點的值(大根堆)陨闹,可以使用數(shù)組來表示一個堆楞捂,C++ 默認提供的是大根堆薄坏。在堆排序中我們有詳細介紹了堆。?圖解排序 6/10 - 堆排序(題目寫出了)寨闹。在這篇文章中胶坠,我們實現(xiàn)了一個堆動手寫個“堆”。?

C++ 中的堆是通過算法實現(xiàn)的繁堡,需要導(dǎo)入?#include <algorithm>

#include?<algorithm>

void?testHeap()?{

vector numbers {6,?20,?7,?3,?5};

/**提供判斷方法*/

// make_heap(numbers.begin(), numbers.end(), [](int a,int b){return a < b;});

// 創(chuàng)建堆后沈善,numbers 中元素的值為: 20,6椭蹄,7闻牡,3,5绳矩,大根堆

make_heap(numbers.begin(), numbers.end(), [](int?a,int?b){return?a < b;});

// 向堆中添加元素

numbers.push_back(40);

// 重組堆:40罩润,6,20埋酬,3哨啃,5,7 大根堆写妥,調(diào)用 push_heap 先確保先前的 vertor 是個堆

push_heap(numbers.begin(), numbers.end());

// 移除堆頂元素拳球,需要把 numbers 中的尾部元素移除,不會自動移除

pop_heap(numbers.begin(), numbers.end());

numbers.pop_back();

}

棧 stack?

棧是一種先進后出的數(shù)據(jù)結(jié)構(gòu)珍特,C++ 底層使用雙端隊列實現(xiàn)祝峻。在以前最小棧算法中我們詳細介紹了這種數(shù)據(jù)結(jié)構(gòu)。?圖解最小棧(LeetCode155. Min Stack)?扎筒。

#include?<stack>

void?testStack()?{

stack s;

s.push(1);

s.pop();

cout?<<?"top="?<< s.top() <<?endl;

s.size();

}

映射 map莱找、unordered_map

map 是一種保存 key 和 vaule 的數(shù)據(jù)結(jié)構(gòu),key 是唯一的嗜桌。C++ 中提供了有序的 map 和無序的 map 「unordered_map」奥溺。

#include?<unordered_map>

#include?<map>

void?testMap()?{

// 初始化

map m;

pair::iterator,?bool> ret_iter =

m.insert(pair("name",?"lefe"));

if?(ret_iter.second ==?false) {

cout?<<?"name have existed"?<<?endl;

}

// 初始化

map m2 = {

{2014,?"iOS"},

{2015,?"Android"},

};

// 單值插入

m["name"] =?"wsy";

// 多值插入

m.insert({{"age",?"20"}, {"from",?"nmg"}});

cout?<<?"size = "?<< m.size() <<?endl;

// 使用迭代器刪除

m.erase(m.begin());

// 查找

map::iterator find_iter = m.find("from");

if?(find_iter != m.end()) {

cout?<<?"find"?<<?endl;

}

// 遍歷, key 是有序的

for?(pair v : m) {

cout?<< v.first <<?" = "?<< v.second <<?endl;

}

// 刪除全部元素

m.clear();

}

pair

pair中保存了兩個值,這兩個值的類型可以是任意類型骨宠,也可以不同浮定。通過 first 和 second 來獲取對應(yīng)的值。

void?testPair()?{

pair p = {"name",?"lefex"};

// 通過first 和 second 來獲取第一個和第二個值

cout?<< p.first;

cout?<< p.second;

}

元組 tuple

它是 pair 的擴充版层亿,可以存儲多個不同類型的元素桦卒。

void?testTuple()?{

pair p = {"name",?"lefe"};

// 創(chuàng)建一個 tuple,類型為 <strinng, int, double, pair>

auto?my_tuple = make_tuple("name",?20,?10.3, p);

// 獲取第一個元素

cout?<<?"0 = "?<< get<0>(my_tuple) <<?endl;

// 獲取第二個元素

cout?<<?"1 = "?<< get<1>(my_tuple) <<?endl;

}

集合 set?

集合中不能存儲相同的元素匿又,它底層基于平衡二叉樹實現(xiàn)方灾,在前面的文章中我們通過二分搜索樹實現(xiàn)了 set。使用 BST 實現(xiàn) Set碌更。在 C++ 中 set 是有序的裕偿,同時也提供了無序的 set 「UnorderSet」洞慎。?

#include?<set>

#include?<unordered_set>

void?testSet()?{

set s {7,?3,?4};

s.insert(5);

// 3,4,5,7

for?(auto?v : s) {

cout?<< v <<?endl;

}

unordered_set us {7,?3,?4};

us.insert(5);

// 7,3,4,5

for?(auto?v : us) {

cout?<< v <<?endl;

}

}

總結(jié)

我們介紹了 C++ 語言本身提供的數(shù)據(jù)結(jié)構(gòu),有線性結(jié)構(gòu)和非線性結(jié)構(gòu)嘿棘。這些數(shù)據(jù)結(jié)構(gòu)在其它語言中幾乎也會提供拢蛋,而且底層實現(xiàn)基本一致,所有只有掌握了這些數(shù)據(jù)結(jié)構(gòu)原理蔫巩,在學習一門其它語言變的非常輕松,調(diào)用 API 時更爽快压。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末圆仔,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蔫劣,更是在濱河造成了極大的恐慌坪郭,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脉幢,死亡現(xiàn)場離奇詭異歪沃,居然都是意外死亡,警方通過查閱死者的電腦和手機嫌松,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進店門沪曙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人萎羔,你說我怎么就攤上這事液走。” “怎么了贾陷?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵缘眶,是天一觀的道長。 經(jīng)常有香客問我髓废,道長巷懈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任慌洪,我火速辦了婚禮顶燕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蒋譬。我一直安慰自己割岛,他們只是感情好,可當我...
    茶點故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布犯助。 她就那樣靜靜地躺著癣漆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪剂买。 梳的紋絲不亂的頭發(fā)上惠爽,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天癌蓖,我揣著相機與錄音,去河邊找鬼婚肆。 笑死租副,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的较性。 我是一名探鬼主播用僧,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼赞咙!你這毒婦竟也來了责循?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤攀操,失蹤者是張志新(化名)和其女友劉穎院仿,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體速和,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡歹垫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了颠放。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片排惨。...
    茶點故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖碰凶,靈堂內(nèi)的尸體忽然破棺而出若贮,到底是詐尸還是另有隱情,我是刑警寧澤痒留,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布谴麦,位于F島的核電站,受9級特大地震影響伸头,放射性物質(zhì)發(fā)生泄漏匾效。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一恤磷、第九天 我趴在偏房一處隱蔽的房頂上張望面哼。 院中可真熱鬧,春花似錦扫步、人聲如沸魔策。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽闯袒。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間政敢,已是汗流浹背其徙。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留喷户,地道東北人唾那。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像褪尝,于是被迫代替她去往敵國和親闹获。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,630評論 2 359

推薦閱讀更多精彩內(nèi)容