學習算法第二天:棧隊列和並查集、哈希表

棧和隊列

•定義:存放數據的線性表

•操作:入棧/隊列、出棧/隊列、判斷滿/空

•空間複雜度:O(n)

•單次操作時間複雜度:O(1)

•區別  先進後出(FILO, First In Last Out) 先進先出(FIFO, First In First Out)

 

棧和隊列的實現方式:數組和鏈表皆可(線性表)

•指針(輔助變量)棧頂/底指針     隊頭/尾指針

•關鍵:出入元素的同時移動指針

三、棧的應用

括號匹配:

•括號、引號等符號是成對出現的,必須相互匹配

•設計一個算法,自動檢測輸入的字符串中的括號是否匹配

•比如:{}[([][])] 匹配      [(])不匹配    (()]不匹配

從左向右掃描字符串

當前是[,期待一個]

當前是(,和剛纔的[不匹配,說明相匹配的符號還在右邊,繼續掃描

當前是[,和剛纔的(不匹配,說明相匹配的符號還在右邊,繼續掃描

當前是],和剛纔的[正好一對,可以從字符串中“刪去”不考慮了

當前是[,目前最近的一個是(,不匹配,繼續掃描

當前是],和剛纔的[正好一對,可以從字符串中“刪去”不考慮了

當前是),目前最近的一個是(,正好一對,可以從字符串中“刪去”不考慮了

當前是],目前最近的一個是[,正好一對,可以從字符串中“刪去”不考慮了,此時左右的括號都匹配成功

總結:從上述過程看,由於括號很多,並不知道最後的括號是什麼,所以採用流處理方式,先進來的括號反而是最後刪除的,所以是先進後出,所以要用棧實現,如下:

依次類推,直至棧爲空;

應用2:四則運算,加減乘除等,平常四則運算如:4*(5-2)+8屬於中綴表達式 需要解析爲後綴表達式:452-*8+;其中需要兩個棧:數字棧和運算符棧。中綴表達式“9+(3-1)*3+10/2”轉化爲後綴表達式爲“9 3 1- 3 * + 10 2 / +”.

1,數字直接入棧

2,如果是(因爲還沒匹配到括號所以直接入棧

3,如果是符合就和棧頂元素比,如果小於等於符合棧棧頂元素,則符號棧頂元素出棧壓入數字棧,直到符合棧頂元素<當前符合優先級爲止。

4,如果是)則直接出棧,直至出棧元素爲匹配的括號爲止。


人工棧模擬系統棧

因爲系統棧可能內存溢出。遞歸隱式的棧調用,無出棧入棧操作,轉爲顯示的棧調用。

1,遞歸是兩步,一是調用跳轉,二是返回back,需要明確

2,空間提前開闢,一個是當前值一個是返回值

如下求n!弄清楚邊界條件,跳轉做什麼,返回做什麼就好。

裏層if語句:當n<=1時,返回值是1,開始往回返回。

外層if語句:往回走發生的事情是,f(n-1)算完了,所以是出棧*f(n-1);

繼續往裏走的事情是n進棧,然後跳轉n-1;

結論:附加了進棧和出棧操作;以及是跳轉還是返回的判斷;外加棧爲空的循環。

遞歸很多,全排列,求組合,並把排列和組合結果輸出,8皇后,漢諾塔

設計一個隊列/棧
支持:出,入,求最大元素
要求所有操作O(1)
一個例子:
3 in, 4 in, 2 in, 5 in, out, out, 6 in, out, out, out
思路:用兩個棧計算,一個數據棧,一個最大元素棧,後續每個元素入棧時,與最大棧中棧頂元素比較,若入棧元素data 大於最大棧棧頂元素,則把data同時壓入兩個棧中,若data小於最大元素棧中棧頂元素,則只壓入棧數據棧中。出棧時,判斷兩個棧頂元素是否相等,若相等則兩個棧同時執行出棧操作,不相等則,只有數據棧執行出棧操作。
並查集
定義:
存放數據的集合關係,如{1,2}{3,4}{5}
支持操作
•     建立新集合
•     查找某個元素屬於哪個集合
•     合併兩個集合
均攤時間複雜度近似O(1)
 
並查集的應用:
• 假設n個節點,初始時點與點之間沒有連接
給出一系列的連接操作
一次連接操作不產生環,則接受,否則被拋棄
 
並查集的實現:
存儲:使用數組標記每個元素屬於的子集
index 1 2 3 4 5 6 7 8
         8 2 3 3 5 5 2 8
合併:直接將根節點屬於的子集改變,根指向根,爲什麼操作根呢,因爲葉子和葉子相互指向就會出現一個節點指向兩個節點的情況,不好存儲。葉子指向根也不好,因爲少了一條邊。
查找:從待查找節點倒推到根節點,即兩個元素是否是一個集合,只要根一致就是一個集合。
優化:路徑壓縮
 
 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章