如果我們一開始就有n個資料,如何將他們快速的建立乙個堆,當然我們可以將堆從空一直執行插入操作,這樣的演算法的複雜度為o(log1+log2+…+logn)經過數學計算這個複雜度是o(nlogn)的。接下來我們介紹一種快速的建立堆的方法,按照資料的順序直接將他們放入樹中,接下來我們從第n/2個資料開始判斷他是否比他的左右兒子小,如果是則不進行任何操作,如果不是,則將左右兒子中小的那個節點和他互換,然後繼續這樣的判斷。然後我們判斷第n/2-1個資料是否滿足,直到判斷到第1個資料。我們來看乙個簡單的例子:假如我們的原始資料是2,8,7,5,3,9,4
這樣的樹顯然不是乙個堆,我們先判斷n/2個資料也就是7是否滿足要求
然後判斷8和2最終的樹就是
我們知道了這樣的演算法我們肯定還有疑問為什麼這樣的演算法會比我們乙個乙個插入的演算法要快,我們來算一算,假如我們的樹有k層,在第j層的節點我們已經知道最多是2j個節點,這些節點最多隻會做k-j次移動,於是我們的總移動次數就是o(k*1+(k-1)*2+(k-2)*4+…(k-(k-1))*2k-1)=o(2k)也就是o(n).所以這個建立堆的方法的複雜度是o(n),比我們單獨插入的複雜度要優秀的多 。
接下來我們來看乙個堆的具體應用。
合併果子:我們有n堆果子,每次可以合併任意兩堆合併的代價是兩堆果子的數量和,問最後將這些果子合併成一堆時所需要的最小的代價。 這樣的乙個問題是有著貪心的做法的,每次選擇果子數最少的兩堆果子將其合併就可以得到最優的解答了。於是我們可以利用我們所學的堆的知識,現將所有的果子數建成乙個堆每次從堆頂拿出乙個數並將它刪除,在拿出乙個數並將它刪除將這兩數的和加入答案,並把他們的和加入堆中。由於將n堆果子合併成一堆果子一共需要合併n-1次,並且每次操作的複雜度是logn的所以完成這樣的乙個問題的複雜度為o(nlogn)
最後大家值得注意的是我們在介紹堆的時候,一直在說每個節點的值比左右兒子節點的值要小的這樣的乙個關係,其實在實現堆的時候,我們所說的小不一定是真正意義上的小的關係,這樣的小的關係是我們自己定義的比如用大於號來定義這樣的乙個小的關係,或者用自己定義的小的關係都能夠實現乙個堆,只是在判斷的時候要注意小的關係就可以了。
資料結構 堆
最大堆 最小堆 堆的定義是 n個元素的序列,當且僅當滿足如下關係時被成為堆 1 ki k2i 且 ki k2i 1 或 2 ki k2i 且 ki k2i 1 i 1,2,n 2 當滿足 1 時,為最小堆,當滿足 2 時,為最大堆。若將此序列對應的一維陣列堪稱是乙個完全二叉樹,則2i和2i 1個節點...
資料結構 堆
資料結構 堆的操作和實現 當應用優先順序佇列或者進行堆排序時,一般利用堆來實現。堆是乙個完全 除最底層 外都是滿的 二叉樹,並滿足如下條件 1 根結點若有子樹,則子樹一定也是堆。2 根結點一定大於 或小於 子結點。因為要求堆必須是完全二叉樹,所以可以用線性的資料結構,比如陣列,來實現堆。利用陣列實現...
資料結構 堆
堆常用來實現優先佇列,在這種佇列中,待刪除的元素為優先順序最高 最低 的那個。在任何時候,任意優先元素都是可以插入到佇列中去的,是電腦科學中一類特殊的資料結構的統稱 最大 最小 堆是一棵每乙個節點的鍵值都不小於 大於 其孩子 如果存在 的鍵值的樹。大頂堆是一棵完全二叉樹,同時也是一棵最大樹。小頂堆是...