記得在學習資料結構的時候一味的想用**實現演算法,重視的是寫出來的**有乙個正確的輸入,然後有乙個正確的輸出,那麼就很滿足了。從網上看了許多的**,看了之後貌似懂了,自己寫完之後也正確了,但是不久之後就忘了,因為大腦在回憶的時候,只依稀記得**中的部分,那麼的模糊,根本不能再次寫出正確的**,也許在第一次寫的時候是因為參考了別人的**,看過之後大腦可以進行短暫的高畫質晰記憶,於是欺騙了我,以為自己寫出來的,滿足了成就感。可是**是計算機識別的,而我們更喜歡文字,影象。所以我們在學習演算法的時候要注重演算法的原理以及演算法的分析,用文字,影象表達出來,然後當需要用的時候再將文字轉換為**。記憶分為三個步驟:編碼,儲存和檢索,就以學習為例,先理解知識,再歸納知識,最後鞏固知識,為了以後的應用而方便檢索知識。
堆分為大根堆和小根堆,是完全二叉樹。大根堆的要求是每個節點的值都不大於其父節點的值,即a[parent[i]] >= a[i]。在陣列的非降序排序中,需要使用的就是大根堆,因為根據大根堆的要求可知,最大的值一定在堆頂。
既然是堆排序,自然需要先建立乙個堆,而建堆的核心內容是調整堆,使二叉樹滿足堆的定義(每個節點的值都不大於其父節點的值)。調堆的過程應該從最後乙個非葉子節點開始,假設有陣列a = 。那麼調堆的過程如下圖,陣列下標從0開始,a[3] = 5開始。分別與左孩子和右孩子比較大小,如果a[3]最大,則不用調整,否則和孩子中的值最大的乙個交換位置,在圖1中是a[7] > a[3] > a[8],所以a[3]與a[7]對換,從圖1.1轉到圖1.2。
所以建堆的過程就是
for ( i = headlen/2; i >= 0; i++)
2:
3:調堆:如果初始陣列是非降序排序,那麼就不需要調堆,直接就滿足堆的定義,此為最好情況,執行時間為θ(1);如果初始陣列是如圖1.5,只有a[0] = 1不滿足堆的定義,經過與子節點的比較調整到圖1.6,但是圖1.6仍然不滿足堆的定義,所以要遞迴調整,一直到滿足堆的定義或者到堆底為止。如果遞迴調堆到堆底才結束,那麼是最壞情況,執行時間為o(h) (h為需要調整的節點的高度,堆底高度為0,堆頂高度為floor(logn) )。do adjustheap(a, heaplen, i)
建堆完成之後,堆如圖1.7是個大根堆。將a[0] = 8 與 a[heaplen-1]交換,然後heaplen減一,如圖2.1,然後adjustheap(a, heaplen-1, 0),如圖2.2。如此交換堆的第乙個元
素和堆的最後乙個元素,然後堆的大小heaplen減一,對堆的大小為heaplen的堆進行調堆,如此迴圈,直到heaplen == 1時停止,最後得出結果如圖3。
輸入:陣列a,堆的長度hlen,以及需要調整的節點i
3:功能:調堆
4:*/
5:
6:void adjustheap(int a, int hlen, int i)
7:
19:
20:if (right < hlen && a[largest] < a[right])
21:
24:
25:if (i != largest) //如果最大值不是父節點
26:
35:else
36:
39: }
40: }
41:
42:/*
43:輸入:陣列a,堆的大小hlen
44:功能:建堆
45:*/
46:void buildheap(int a, int hlen)
47:
54: }
55:
56:/*
57:輸入:陣列a,待排序陣列的大小alen
58:功能:堆排序
因此,建堆的執行時間是o(n)。
總執行時間t(n) = o(nlogn) + o(n) = o(nlogn)。對於堆排序的最好情況與最壞情況的執行時間,因為最壞與最好的輸入都只是影響建堆的執行時間o(1)或者o(n),而在總體時間中佔重要比例的是迴圈調堆的過程,即o(nlogn) + o(1) =o(nlogn) + o(n) = o(nlogn)。因此最好或者最壞情況下,堆排序的執行時間都是o(nlogn)。而且堆排序還是原地演算法(in-place algorithm)。
如果不太了解o,θ等漸進符號的,可以參考博文:計算機演算法分析之漸進記號。 上述文章是我的學習筆記,如有錯誤,還望不吝賜教。
選擇排序及其改進 堆排序
include include iomanip using namespace std 選擇排序思想 每一趟 如第i趟 從後面n i 1個待排序的元素中選出關鍵字最小的元素,作為有序子串行 前i 1個有序 的第i個元素,直至n 1趟結束。因為最後乙個元素是不用再排序的 沒有比它再小的元素了,他是最後...
堆排序演算法及其應用
堆積排序是指利用堆積樹 堆 這種資料結構所設計的一種排序演算法,可以利用陣列的特點快速定位指定索引的元素。堆可以被看成是一棵樹,結點在堆中的高度可以被定義為從本結點到葉子結點的最長簡單下降路徑上邊的數目 定義堆的高度為樹根的高度。我們將看到,堆結構上的一些基本操作的執行時間至多是與樹的高度成正比,為...
堆排序分析實現
演算法思想 若公升序,建大堆,每次選擇堆頂元素即最大的數,和最後一位交換,再縮小堆的範圍 避免剛排好的最後乙個位置被調回去 對剩下的進行向下調整 此時只有根節點不對,左右子樹都滿足大堆 反覆進行直到堆的範圍為0.則資料就有序了。實現思路 堆排序的實現首先是需要將陣列調整為乙個大堆或者小堆,然後就是迴...