堆是一棵徹底二叉樹,其中每一個元素大於等於其全部子結點的值。準確的說這是最大堆(maxheap)的定義,堆還能夠是最小堆(minheap),即每一個元素都小於等於它的孩子html
堆有三種基本操做:node
3.刪除最大元素
策略:由堆的特性得知,最大元素在根上,因此刪除最大元素就是要刪除根結點,而後將餘下的兩個分開的子樹從新構造爲堆。git
利用最後的葉結點來取代根,而後將其向下移動到合適的位置。
算法
堆排序是先將一組元素一項項地插入到堆中,而後一次刪除一個,由於元素最早從堆中刪除(在最大堆中),從堆中獲得的元素序列將是有序序列,並且是降序的,相似地,一個最小堆可用來獲得升序的排序結果。
算法思路:每次將堆的堆頂記錄輸出;同時調整剩餘的記錄,使他們從新排成一個堆。重複以上過程。
1)將初始待排序關鍵字序列(R1,R2....Rn)構建成大頂堆,此堆爲初始的無須區;
2)將堆頂元素R[1]與最後一個元素R[n]交換,此時獲得新的無序區(R1,R2,......Rn-1)和新的有序區(Rn),且知足R[1,2...n-1]<=R[n];
3)因爲交換後新的堆頂R[1]可能違反堆的性質,所以須要對當前無序區(R1,R2,......Rn-1)調整爲新堆,而後再次將R[1]與無序區最後一個元素交換,獲得新的無序區(R1,R2....Rn-2)和新的有序區(Rn-1,Rn)。不斷重複此過程直到有序區的元素個數爲n-1,則整個排序過程完成。(轉)api
public int[] heapSort(int[] array){ array = buildMaxHeap(array); for(int i=array.length-1;i>1;i--){ int temp = array[0]; array[0] = array[i]; array[i] = temp; adjustDownToUp(array, 0,i); } return array; }
代碼實現思路:首先初始建堆,array[0]爲第一趟值最大的元素, 將堆頂元素和堆低元素交換,即獲得當前最大元素正確的排序位置,最後將剩餘的元素整理成堆。數據結構
優先隊列(priority queue)是一個服從兩個有序規則的集合。首先,具備更高優先級的項排在前面,其次,具備相同優先級的項按先進先出的規則排序。post
優先隊列不是FIFO隊列,它根據優先級排序元素,而不是根據它們進入隊列的次序排序。學習
可用多個隊列來實現優先隊列,具備相同優先級的項保存在一個隊列中。對於這個問題的更好的解決方案是使用堆。若是按優先級進行排序,就能看出優先隊列和堆之間存在的天然關係,但要注意的是,具備相同優先級的項採用先進先出的原則,並無自動應用到堆中。測試
getMax()
方法在LinkedMaxHeap類中已經給出了add的方法,能夠知道add方法中引用HeapNode中排序的方法,將元素與其的左右子結點進行比較,若子結點大於父結點,則交換兩者。因此創建測試用例中添加大小順序不一樣的數入堆中就已經排好序,已知最大堆中根結點是最大元素,因此getMax()能夠直接返回根結點。`return root.getElement();` - 問題2:完成PP18.5,實現堆排序算法
public static class HeapSort {
private int[] buildMaxHeap(int[] array) {
//從最後一個節點array.length-1的父節點(array.length-1-1)/2開始,直到根節點0,反覆調整堆
for (int i = (array.length - 2) / 2; i >= 0; i--) {
adjustDownToUp(array, i, array.length);
}
return array;
}ui
private void adjustDownToUp(int[] array, int k, int length) { int temp = array[k]; for (int i = 2 * k + 1; i < length - 1; i = 2 * i + 1) { if (i < length && array[i] < array[i + 1]) { i++; } if (temp >= array[i]) { break; } else { array[k] = array[i]; k = i; } } array[k] = temp; } public int[] heapSort(int[] array) { array = buildMaxHeap(array); for (int i = array.length - 1; i > 1; i--) { int temp = array[0]; array[0] = array[i]; array[i] = temp; adjustDownToUp(array, 0, i); } return array; } public void toString(int[] array) { for (int i : array) { System.out.print(i + " "); } } }
解答:首先初始創建最大堆,array[0]爲第一趟值最大的元素, 將堆頂元素和堆低元素交換,即獲得當前最大元素正確的排序位置,最後將剩餘的元素整理成堆。 - 1)將存放在array[0,...,n-1]中的n個元素建成初始堆; - 2)將堆頂元素與堆底元素進行交換,則序列的最大值即已放到正確的位置; - 3)但此時堆被破壞,將堆頂元素向下調整使其繼續保持大根堆的性質,再重複第23步,直到堆中僅剩下一個元素爲止。 --- ## [代碼託管](https://git.oschina.net/pdds2017/LXR20162320.git) ![](http://images2017.cnblogs.com/blog/1062815/201711/1062815-20171106205555934-2054422197.png) (statistics.sh腳本的運行結果截圖) --- ## 上週考試錯題總結 - 錯題1:
Which of the following best describes a balanced tree?
A .A balanced trees has all nodes at exactly the same level.
B .A balanced tree has no nodes at exactly the same level.
C .A balanced tree has half of the nodes at one level and half the nodes at another level.
D .A balanced tree has all of the nodes within one level of each other.
E .none of the above correctly describe a balanced tree.
解答:D,我選的是E,我認爲ABCD四個選項描述平衡樹的概念都不完整或片面。好比說答案A,儘管樹的節點在同一層次上是平衡的,但並非全部的平衡樹都有這個屬性。全部A錯誤。相對其餘選項只有D是正肯定義了平衡樹。 - 錯題2:
In a postorder traversal, the root is the last element visited in the tree.
A .true
B .false
```
解答:B,這個題目答案應該是給錯了,由於答案給的是在後序遍歷中根是最後訪問的一個元素,這應該和A選項符合。
You have to fight to reach your dream. You have to sacrifice and work hard for it. 爲了實現夢想,你必須奮鬥;你必須作出犧牲,必須爲之努力。調整心態,繼續前行,將來加油。
代碼行數(新增/累積) | 博客量(新增/累積) | 學習時間(新增/累積) | 重要成長 | |
---|---|---|---|---|
目標 | 5000行 | 30篇 | 400小時 | |
第一週 | 188 | 1/1 | 25 | 算法分析 |
第二週 | 70/258 | 1/2 | 15/40 | 《構建之法》7-9章 |
第三週 | 474/732 | 1/3 | 20/60 | 查找和排序 |
第四五六週 | 1313/2045 | 4/7 | 12/72 | 棧和隊列 |
第七週 | 890/2935 | 1/8 | 14/86 | 樹 |
第八週 | 913/3848 | 1/9 | 20/106 | 二叉查找樹 |
第九周 | 890/3738 | 1/10 | 13/119 | 堆 |
第十週 |
(有空多看看現代軟件工程 課件 軟件工程師能力自我評價表)