堆排序java实例_堆排序(示例代码)
前言:網上有很多堆排序的案例,我只想寫自己堆排序。
一:堆結構
即:一個父節點最多只能有兩個子節點(可以沒有),如下圖
圖1
? ? ? ?圖2
? ? ? ? ? 圖3
? ? ? 圖4
二: 數組與堆結構轉換
假設已知堆數組? ?int[]? a = {9,7,6,4,5,1,3,2,}? 則相應對結構如下
圖5
備注: 一個父節點(pNode? 為圖5中的7 )和兩個子節點(4(lNOde 左節點)和5(rNode 右節點))的關系
左節點: lNOde?=? 2*pNode? ?+ 1? ;
右節點 : rNode? = 2*pNode? ? +2 ;
三:通過已知數組建立成堆結構數組
假設已知數組? ?int[] a = { 7,9,6,4,5,1,3,2};
思路:對一個已知堆結構數組(長度為n)中添加一個元素,并調整該結果使之成為新的堆結構數組(長度變成 n+1)
步驟一:獲取該數組的第一個元素 7 (a[0])為已知堆數組。
步驟二 :獲取該數組的第下一個元素9(a[1])并添加到上一個堆結構數組中,并判斷其的父節點是否大于自己,如果大于則交換父節點與自己的位置,交換后自己就在父節點的位置并把自己當成新的子節點,繼續尋找父節點直至自己小于父節點并返回。如果大于則已是堆結構返回。以此類推直至成為新的堆結構。
步驟三 :重復步驟二,直至數組最后一個元素。
java實現:
/*** 建立堆模型
*
*@parama*/
private static void buildHeat(int[] a) {for (int i = 1; i < a.length; i++) { //注意我是從數組的第二個位置(即 index = 1)開始的int parentNodeIndex =getParentNodeIndex(i);int currentIndex =i;while (parentNodeIndex >= 0) {//判斷子節點是否大于父節點
if (a[parentNodeIndex]
int temp =a[parentNodeIndex];
a[parentNodeIndex]=a[currentIndex];
a[currentIndex]=temp;
}else{// break; //步驟2 :自己小于父節點結束循環(while)已成為新的堆結構。>>>>>>>執行步驟3
}
currentIndex=parentNodeIndex; //步驟2 把自己當成新的子節點
parentNodeIndex=getParentNodeIndex(parentNodeIndex);
}
}
}
四:去堆(獲取排序)
步驟一:因為堆頂是整個堆結構中最大的數,所以我獲取堆頂的哪個數9(a[0]? 如圖5),并把堆中最后一個數2(如圖5)放入堆頂 (此時的數組長度是原來數組長度的減一)
步驟二 :調整堆結構(因為上一個步驟把 最后一個數放入如堆頂).。
調整方法:? ?獲取獲取左右子節點,先判斷是否有子節點,然后判斷兩個子節點的大小(假設9已經換成了2,當前它有兩個子節點,7(左子節點) 6 (右子節點)),獲取到最大的子節點(7),并于父節點(2)比較 ,如果子節點大于父節點,交換父節點與子節點的位置,并把當前自己成為新的父節點重復調整方法,直至沒有子節點或父節點大于所有子節點。成為新的堆結構
步驟三 :重復步驟一和二 ,直至沒有改結構中沒有子節點。
java實現
備注:代碼與步驟二的調整方法有些不同 ,因為 1)如果沒有左節點 (調整結束) 就一定不會有右節點?。2)如果有右節點就一定有左節點?。3)如果只有左節點沒有右節點?
//去除堆 》》即排序
for(int j = 0; j < a.length; j++) {int lastIndex = a.length - 1 -j;int currentIndex = 0;int temp2 = a[0]; //步驟1 : 獲取堆結構中的最大數 并與最后一個數交換位置
a[0] =a[lastIndex];
a[lastIndex]=temp2;while(true) {//獲取左節點
int leftChildNodeIndex =getLeftChildNodeIndex(currentIndex); //步驟2 獲取左節點位置if(leftChildNodeIndex >=lastIndex) { //判斷做節點是否有 有數//沒有左節點子節點 即去堆完成
for (int i = 0; i < a.length ; i++) {
System.out.print(a[i]+ ",");
}
System.out.println("沒有左節點子節點 即去堆完成");break; //步驟3
}//獲取右節點
int rightChildNodeIndex =getRightChildNodeIndex(currentIndex);if(rightChildNodeIndex >=lastIndex) { //獲取右節點//沒有右子節點 但有左節點 需要進行 交換
if (a[leftChildNodeIndex] >a[currentIndex]) {//判斷左子節點 大于父節點 需要交換位置
int temp =a[leftChildNodeIndex];
a[leftChildNodeIndex]=a[currentIndex];
a[currentIndex]=temp;
}for (int i = 0; i < a.length ; i++) {
System.out.print(a[i]+ ",");
}
System.out.println("沒有右子節點 但有左節點");break; //步驟3
}//即有左節點又有有節點//先判斷左右節點的大小 返回大節點
int whichIndexBig = a[leftChildNodeIndex] > a[rightChildNodeIndex] ?leftChildNodeIndex : rightChildNodeIndex;//判斷子節點是否大于符節點
if (a[whichIndexBig] >a[currentIndex]) {//子節點大于父節點 需要交換子父節點的位置
int temp =a[whichIndexBig];
a[whichIndexBig]=a[currentIndex];
a[currentIndex]=temp;
}//當前父節點
currentIndex =whichIndexBig; //
}
}
五 完整代碼實現如下
packagecom.jinliang.sort;public classHeatSort {public static voidmain(String[] args) {int[] a = { 7,4,6,9,5,1,3,2};//創建堆數組
buildHeat(a);for (int j = 0; j < a.length; j++) {
System.out.print(a[j]+ ",");
}
System.out.println("建隊完成");//int[] a = {42, 88, 77, 76, 66, 55, 64, 52, 45, 54, 34, 2, 32, 12, 35, 1, 22, 21, 34, 3};//去除堆 》》即排序
for(int j = 0; j < a.length; j++) {int lastIndex = a.length - 1 -j;int currentIndex = 0;int temp2 = a[0];
a[0] =a[lastIndex];
a[lastIndex]=temp2;while(true) {//獲取左節點
int leftChildNodeIndex =getLeftChildNodeIndex(currentIndex);if(leftChildNodeIndex >=lastIndex) {//沒有左節點子節點 即去堆完成
for (int i = 0; i < a.length ; i++) {
System.out.print(a[i]+ ",");
}
System.out.println("沒有左節點子節點 即去堆完成");break;
}//獲取右節點
int rightChildNodeIndex =getRightChildNodeIndex(currentIndex);if(rightChildNodeIndex >=lastIndex) {//沒有右子節點 但有左節點 需要進行 交換
if (a[leftChildNodeIndex] >a[currentIndex]) {//判斷左子節點 大于父節點 需要交換位置
int temp =a[leftChildNodeIndex];
a[leftChildNodeIndex]=a[currentIndex];
a[currentIndex]=temp;
}for (int i = 0; i < a.length ; i++) {
System.out.print(a[i]+ ",");
}
System.out.println("沒有右子節點 但有左節點");break;
}//即有左節點又有有節點//先判斷左右節點的大小 返回大節點
int whichIndexBig = a[leftChildNodeIndex] > a[rightChildNodeIndex] ?leftChildNodeIndex : rightChildNodeIndex;//判斷子節點是否大于符節點
if (a[whichIndexBig] >a[currentIndex]) {//子節點大于父節點 需要交換子父節點的位置
int temp =a[whichIndexBig];
a[whichIndexBig]=a[currentIndex];
a[currentIndex]=temp;
}//當前父節點
currentIndex =whichIndexBig;
}
}//輸出排序后的數組
for (int i = 0; i < a.length; i++) {
System.err.print(a[i]+ ",");
}
}/*** 建立堆模型
*
*@parama*/
private static void buildHeat(int[] a) {for (int i = 1; i < a.length; i++) {int parentNodeIndex =getParentNodeIndex(i);int currentIndex =i;while (parentNodeIndex >= 0) {//判斷子節點是否大于父節點
if (a[parentNodeIndex]
總結
以上是生活随笔為你收集整理的堆排序java实例_堆排序(示例代码)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机网络云南大学实验四,云南大学软件学
- 下一篇: excel如何去重统计户数_公式解读第三