Java實現堆排序(大根堆)

來源:互聯網
上載者:User

標籤:

  堆排序是一種樹形選擇排序方法,它的特點是:在排序的過程中,將array[0,...,n-1]看成是一顆完全二叉樹的順序儲存結構,利用完全二叉樹中雙親節點和孩子結點之間的內在關係,在當前無序區中選擇關鍵字最大(最小)的元素。

1. 若array[0,...,n-1]表示一顆完全二叉樹的順序儲存模式,則雙親節點指標和孩子結點指標之間的內在關係如下:

  任意一節點指標 i:父節點:i==0 ? null : (i-1)/2

            左孩子:2*i + 1

            右孩子:2*i + 2

2. 堆的定義:n個關鍵字序列array[0,...,n-1],若且唯若滿足下列要求:(0 <= i <= (n-1)/2)

      ① array[i] <= array[2*i + 1] 且 array[i] <= array[2*i + 2]; 稱為小根堆;

      ② array[i] >= array[2*i + 1] 且 array[i] >= array[2*i + 2]; 稱為大根堆;

3. 建立大根堆:

  n個節點的完全二叉樹array[0,...,n-1],最後一個節點n-1是第(n-1-1)/2個節點的孩子。對第(n-1-1)/2個節點為根的子樹調整,使該子樹稱為堆。

  對於大根堆,調整方法為:若【根節點的關鍵字】小於【左右子女中關鍵字較大者】,則交換。

  之後向前依次對各節點((n-2)/2 - 1)~ 0為根的子樹進行調整,看該節點值是否大於其左右子節點的值,若不是,將左右子節點中較大值與之交換,交換後可能會破壞下一級堆,於是繼續採用上述方法構建下一級的堆,直到以該節點為根的子樹構成堆為止。

  反覆利用上述調整堆的方法建堆,直到根節點。

4.堆排序:(大根堆)

  ①將存放在array[0,...,n-1]中的n個元素建成初始堆;

  ②將堆頂元素與堆底元素進行交換,則序列的最大值即已放到正確的位置;

  ③但此時堆被破壞,將堆頂元素向下調整使其繼續保持大根堆的性質,再重複第②③步,直到堆中僅剩下一個元素為止。

堆排序演算法的效能分析:

  空間複雜度:o(1);

  時間複雜度:建堆:o(n),每次調整o(log n),故最好、最壞、平均情況下:o(n*logn);

  穩定性:不穩定

 

建立大根堆的方法:

 1     //構建大根堆:將array看成完全二叉樹的順序儲存結構 2     private int[] buildMaxHeap(int[] array){ 3         //從最後一個節點array.length-1的父節點(array.length-1-1)/2開始,直到根節點0,反覆調整堆 4         for(int i=(array.length-2)/2;i>=0;i--){  5             adjustDownToUp(array, i,array.length); 6         } 7         return array; 8     } 9     10     //將元素array[k]自下往上逐步調整樹形結構11     private void adjustDownToUp(int[] array,int k,int length){12         int temp = array[k];   13         for(int i=2*k+1; i<length-1; i=2*i+1){    //i為初始化為節點k的左孩子,沿節點較大的子節點向下調整14             if(i<length && array[i]<array[i+1]){  //取節點較大的子節點的下標15                 i++;   //如果節點的右孩子>左孩子,則取右孩子節點的下標16             }17             if(temp>=array[i]){  //根節點 >=左右子女中關鍵字較大者,調整結束18                 break;19             }else{   //根節點 <左右子女中關鍵字較大者20                 array[k] = array[i];  //將左右子結點中較大值array[i]調整到雙親節點上21                 k = i; //【關鍵】修改k值,以便繼續向下調整22             }23         }24         array[k] = temp;  //被調整的結點的值放人最終位置25     }    

堆排序:

 1     //堆排序 2     public int[] heapSort(int[] array){ 3         array = buildMaxHeap(array); //初始建堆,array[0]為第一趟值最大的元素 4         for(int i=array.length-1;i>1;i--){   5             int temp = array[0];  //將堆頂元素和堆低元素交換,即得到當前最大元素正確的排序位置 6             array[0] = array[i]; 7             array[i] = temp; 8             adjustDownToUp(array, 0,i);  //整理,將剩餘的元素整理成堆 9         }10         return array;11     }

刪除堆頂元素(即序列中的最大值):先將堆的最後一個元素與堆頂元素交換,由於此時堆的性質被破壞,需對此時的根節點進行向下調整操作。

1     //刪除堆頂元素操作2     public int[] deleteMax(int[] array){3         //將堆的最後一個元素與堆頂元素交換,堆底元素值設為-999994         array[0] = array[array.length-1];5         array[array.length-1] = -99999;6         //對此時的根節點進行向下調整7         adjustDownToUp(array, 0, array.length);8         return array;9     }

對堆的插入操作:先將新節點放在堆的末端,再對這個新節點執行向上調整操作。

假設數組的最後一個元素array[array.length-1]為空白,新插入的結點初始時放置在此處。

 1     //插入操作:向大根堆array中插入資料data 2     public int[] insertData(int[] array, int data){ 3         array[array.length-1] = data; //將新節點放在堆的末端 4         int k = array.length-1;  //需要調整的節點 5         int parent = (k-1)/2;    //雙親節點 6         while(parent >=0 && data>array[parent]){ 7             array[k] = array[parent];  //雙親節點下調 8             k = parent; 9             if(parent != 0){10                 parent = (parent-1)/2;  //繼續向上比較11             }else{  //根節點已調整完畢,跳出迴圈12                 break;13             }14         }15         array[k] = data;  //將插入的結點放到正確的位置16         return array;17     }

 

測試:

 1     public void toString(int[] array){ 2         for(int i:array){ 3             System.out.print(i+" "); 4         } 5     } 6      7     public static void main(String args[]){ 8         HeapSort hs = new HeapSort(); 9         int[] array = {87,45,78,32,17,65,53,9,122};10         System.out.print("構建大根堆:");11         hs.toString(hs.buildMaxHeap(array));12         System.out.print("\n"+"刪除堆頂元素:");13         hs.toString(hs.deleteMax(array));14         System.out.print("\n"+"插入元素63:");15         hs.toString(hs.insertData(array, 63));16         System.out.print("\n"+"大根堆排序:");17         hs.toString(hs.heapSort(array));    18     }
1 構建大根堆:122 87 78 45 17 65 53 9 32 2 刪除堆頂元素:87 45 78 32 17 65 53 9 -99999 3 插入元素63:87 63 78 45 17 65 53 9 32 4 大根堆排序:9 17 32 45 53 63 65 78 87 

 

Java實現堆排序(大根堆)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.