最基本的資料結構:棧、佇列、鍊錶、二叉樹。這一篇主要實現前三種資料結構,記錄一部分習題的思路。這一篇比較簡單,但算是學習更高階資料結構的良好開端吧。
先進後出。最主要的方法是push(element)個pop(),前者壓入乙個元素,後者彈出乙個元素。用陣列實現乙個簡單的棧。
/*stack
*/template
class
xstack;
template
xstack::xstack(int
size)
template
bool xstack::push(t input)
else
return
true;}
template
t xstack::pop()
else
}
先進先出。最主要的方法是enqueue(element)和dequeue(),前者在佇列尾部壓入乙個元素,後者從佇列頭部彈出乙個元素。用陣列實現乙個簡單的佇列。
/*queue
*/template
class
xqueue;
template
xqueue::xqueue(int
size)
template
bool xqueue::enqueue(t input)
else
}template
t xqueue::dequeue()
else
}template
int xqueue::step(int
pos)
else
else
}}
鍊錶(與其說是一種資料結構)不如說是一種組織資料的思想,即將指標作為結構體的乙個屬性以指向與結構體本身關聯的其他同型別結構體。很多其他高階的資料結構實際上都是鍊錶。這裡僅僅簡單實現乙個單向鍊錶。
/*linklist
*/template
class
xnode;
template
xnode::xnode()
template
xnode::xnode(t data)
template
class
xlinklist;
template
xlinklist::xlinklist()
template
xnode* xlinklist::search(t value)
tmp = tmp->next;
}return
null;
}template
void xlinklist::insert(t input)
template
bool xlinklist::deletenode(xnode*node)
tmp = tmp->next;
}if (prevnode ==null)
prevnode->next = node->next;
return
true
;}
練習10.1-2使用乙個陣列實現兩個棧,使得push(element)和pop()的代價都為 $o(1)$ 。思路:陣列兩端作為棧低,棧頂相向。
練習10.1-6使用兩個棧實現乙個佇列,分析操作代價。思路:乙個空棧乙個滿棧,enqueue(element)操作正常向滿棧push(element),代價為 $o(1)$;dequeue()操作先將滿棧全部pop()出來,出來乙個就壓到空棧裡面,結束後對空棧(此時非空了)pop(),結果作為dequeue的結果返回,再將空棧(此時非空)元素全部pop()回滿棧(此時已空),代價為 $o(n)$ 。
練習10.1-7使用兩個佇列實現乙個棧,分析操作代價。思路,乙個空佇列乙個滿佇列,push(element)操作正常向滿佇列enqueue(element),代價為 $o(1)$ ;pop()操作先將滿佇列元素乙個乙個dequeue()出來並enqueue(element)到另乙個空佇列裡面,直到最後乙個不執行enqueue(element) ,卻返回作為pop()的返回值,代價為 $o(n)$ 。
練習10.2-8對鍊錶中的每個元素僅使用乙個指標 np 而不是 next 和 pre ,實現雙向列表。假設指標值為 $k$ 位整形數。提示使用異或的特性。
思路:對於二進位制的 $k$ 位整數, 如果 a xor b = c 則 a xor c=b and b xor c=a 。所以設定 np 為該元素前乙個元素位址和後乙個元素位址的異或值,這樣每知道乙個節點的後乙個節點位址,就可以知道前乙個節點位址,反之亦可。第乙個節點的位址是已知的(這樣才能訪問到該節點的 np 指標),而且第乙個節點的前乙個節點不存在,位址為 $0$ ,所以可以通過 0 xor np[1] 獲得第二個節點的位址。
練習10.4-3寫出乙個 $o(n)$ 時間的非遞迴過程,將給定的 $n$ 各節點的二叉樹中的每個節點的 $key$ 值輸出。利用棧作為輔助資料結構。
思路:從根節點開始迭代。首先,輸出關鍵字。然後判斷當前節點是否是葉子節點:如果不是,判斷是否有右節點,若有則將右節點壓入棧;不管是否有右節點,當前節點進入左節點繼續迭代;如果是葉子節點,從棧中彈出乙個節點作為當前節點。如果棧空了,則結束。
練習10.4-5寫乙個 $o(n)$ 的非遞迴過程,將給定的 $n$ 各節點的二叉樹中的每個節點的 $key$ 值輸出。只能利用固定量的額外儲存空間,也不能修改樹(即使是暫時的)。
思路:抵達當前節點,先判斷從何處抵達該節點:如果是從父節點到達當前節點的,先輸出值,再判斷是否是葉子節點,如果是,直接返回父節點,如果不是則進入左節點;如果是從左節點到達當前節點的,判斷是否有右節點,如果有則進入右節點,如果沒有則進入父節點;如果是從右節點進入該節點的,直接進入父節點。(這是前序的版本,也有中序和後序,差異就是在何處輸出值。)該方法需要二叉樹是雙向鍊錶,即左節點和右節點能夠訪問到父節點,否則還是需要用棧或者遞迴。
演算法 基本資料結構
1 後進先出 2 棧有乙個屬性為s.top執行最新插入的元素 3 彈出稱為pop,插入稱為push 4 上溢和下溢 如果試圖對乙個空棧執行彈出操作,則稱為下溢 如果s.top超過了n,則稱為上溢,在下面偽 中不考慮上溢問題 1 先進先出 2 佇列有對頭head和對尾tail 3 插入稱為入隊 enq...
5 基本資料結構 集合
集合 set 是乙個無序的不重複元素序列。可以使用大括號或者set 函式建立集合,注意 建立乙個空集合必須用set 而不是,因為是用來建立乙個空字典。1.建立空集合1.set test 2.set 2.集合操作 print basket a set abracadabra print a b set...
演算法導論第十章 基本資料結構
集合 如同在數學中一樣,集合也是電腦科學的基礎。不過數學上的集合時不變的,而演算法所操作的集合是動態改變的。資料結構這一部分介紹在計算機中表示和操作有窮動態集合的一些基本技術。字典 許多演算法要求能夠將元素插入集合,從集合中刪除元素,以及測試元素是否屬於集合。支援這些操作的動態集合就叫字典。另一些演...