堆以及堆排序實現

2021-09-30 12:56:11 字數 1644 閱讀 2532

1.今天實現了一下堆排序,這裡的堆是指二叉堆,至於二項堆和斐波那契堆以後再說。

先看二叉堆的定義:

二叉堆是完全二叉樹或近似完全二叉樹。

滿足特性是:父親節點的值大於等於(小於等於)左右孩子的值,並且左右子樹也是二叉堆。對應的二叉堆是大頂堆(小頂堆)。

二叉堆是完全二叉樹,可以用線性表來儲存。

2.實現堆排序時的想法:

(1)乙個關鍵點是堆的調整,調整的時候一定要注意先找到左右孩子中較大(小)的數的位置,這是可能被置換的位置,因為置換後,這個被置換的位置就變成了新的要調整的位置了,我們需要從它開始往下繼續調整(因為置換後,有可能破壞了下邊的堆結構)。

(2)步驟:先把陣列調整成大(小)頂堆。開始調整的位置為length/2向下取整,從這開始,一直調整到根節點,即陣列下標為1的值。

然後把堆頂元素和最後乙個元素置換,繼續調整剩下的length-1 個數了,因為這裡共n-1次調整,每次開始調整位置都是從根節點開始調整,只是變了長度,所以這裡可以迴圈呼叫調整函式n-1次。

3.下邊是具體**

//堆排序

//1.從乙個節點往下調整

//2.構造堆:其實就是堆length/2 - 1那個節點開始直到0,都執行往下調整操作

//3.排序:取堆頂元素與length-i替換,再做調整

//構造大頂堆

func less(i, j int) bool

func heapajustfromonenode(h int, i0, length int) bool

j := j1

if j2 := j1 + 1; j2 < length && less(h[j2], h[j1])

if !less(h[j], h[i])

h[j], h[i] = h[i], h[j] //swap操作

i = j //i更新為下交換後的節點下標

} return i > i0 //判斷本次從i0節點開始向下調整,是否有交換操作

}func genheap(h int)

}func heapsort(h int)

}func printslice(h int)

fmt.println()

}func main()

fmt.println("排序前:")

printslice(h)

heapsort(h)

fmt.println("排序後:")

printslice(h)

}

4.複雜度分析

時間消耗主要是:

(1)先把陣列調整成堆,即建堆的過程。消耗時間為:1+2+...+log2n ,其中數值代表的是調整位置最多置換的次數(個人理解),它是線性的,為o(n).

(2)調整堆的過程,這在建堆和排序時都會被用到,因為在後邊的n-1次調整中,開始位置都是從根節點開始,即最多有log2n次置換。

(3)所以排序時為o(nlogn)

空間複雜度為o(1);

5.特點

堆排序和直接選擇排序相反:在任何時刻堆排序中無序區總是在有序區之前,且有序區是在原向量的尾部由後往前逐步擴大至整個向量為止。

其他效能:由於建初始堆所需的比較次數較多,所以堆排序不適宜於記錄數較少的檔案。

堆排序是不穩定的排序。

堆以及php實現堆排序

什麼是堆 這裡的堆 二叉堆 指得不是堆疊的那個堆,而是一種資料結構。堆可以視為一棵完全的二叉樹,完全二叉樹的乙個 優秀 的性質是,除了最底層之外,每一層都是滿的,這使得堆可以利用陣列來表示,每乙個結點對應陣列中的乙個元素.陣列與堆之間的關係 二叉堆一般分為兩種 最大堆和最小堆。什麼是最大堆 堆中每個...

堆以及堆排序

二叉 堆 乙個類似完全二叉樹的資料結構 左孩子 2i 右孩子 2i 1 父節點 i 2 以上結論如果記不住,用到時可以自己畫個圖推一下 物理儲存 用陣列儲存a 1,2,3.n 1.調整每個節點的演算法 如果要建立大頂堆,則需遵循每個父親結點的值都要大於左右孩子的值 遞迴版本 param number...

堆以及堆排序詳解

記錄一下自己理解的堆和堆排序吧。堆是一種類似於完全二叉樹的樹形結構,對於二叉樹中所有非葉子節點,如果根節點的值嚴格大於其兩個兒子的值,則稱為 大頂堆,反之稱為小頂堆。堆排序的一般步驟 首先利用已有的資料構造乙個堆,大頂堆增序,小頂堆降序。將堆頂的元素與堆末元素交換,接著重新調整剩下的元素為乙個堆,直...