排序演算法之堆排序演算法的實現
阿新 • • 發佈:2019-01-07
在做一份筆試題時,發現對堆排序演算法還不甚瞭解,所以趕緊了解了一下相關思想和概念,並嘗試自身實現了一下,在這附上概念思想以及程式碼的實現。
堆排序:利用堆資料結構而設計的一種排序演算法,堆排序是一種選擇排序,它的最壞,最好,平均時間複雜度均為O(nlogn),它也是不穩定排序。首先簡單瞭解下堆結構。堆是具有以下性質的完全二叉樹:每個結點的值都大於或等於其左右孩子結點的值,稱為大頂堆;或者每個結點的值都小於或等於其左右孩子結點的值,稱為小頂堆。
該陣列從邏輯上講就是一個堆結構,用簡單公式來描述一下堆的定義就是:
大頂堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]
小頂堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]
堆排序思想及步驟:
基本思想:
將待排序序列構造成一個大頂堆,此時,整個序列的最大值就是堆頂的根節點。將其與末尾元素進行交換,此時末尾就為最大值。然後將剩餘n-1個元素重新構造成一個大頂堆,這樣會得到n個元素的次小值。如此反覆執行,便能得到一個有序序列了
步驟:
a.將無需序列構建成一個堆,根據升序降序需求選擇大頂堆或小頂堆;
b.將堆頂元素與末尾元素交換,將最大元素"沉"到陣列末端;
c.重新調整結構,使其滿足堆定義,然後繼續交換堆頂元素與當前末尾元素,反覆執行調整+交換步驟,直到整個序列有序。
程式碼實現:
public class HeapSort implements SortableInterface { @Override public void sort(int[] array) { for(int length = array.length ; length > 1 ; length --) { //從最後一個非葉子節點開始,調整堆的順序,構建大頂堆 for(int i = length/2 - 1 ; i >= 0 ; i --) { adjustHeap(array, i , length); } //將當前堆的根節點與最後一個葉子節點交換 swap(array , 0 , length -1); } for(int i = 0 ; i < array.length ; i++) System.out.print(array[i] + " "); } //調整當前節點及其子節點的位置 public void adjustHeap(int[] array , int i , int length) { //噹噹前節點具有左右節點時,需要調整該節點與其子節點的位置 if(2 * i + 1 < length && 2 * i + 2 < length) { int index = findMax(array , i , 2 * i + 1 ,2 * i + 2); if(i != index) { swap(array , i , index); //重新調整該節點及其子節點的位置,如果有的話 adjustHeap(array , index , length); } }else if(2 * i + 1 < length) { //當只具有左位元組點時,只調整該節點與左位元組點的位置 int index = findMax(array , i , 2 * i + 1 ); if(i != index) { //交換i位置與index位置的節點 swap(array , i , index); //重新調整該節點及其子節點的位置,如果有的話 adjustHeap(array , index , length); } } } //查詢最大的節點位置 public int findMax(int[] array , int...indexs) { //定義最大值的索引,預設為indexs的第一個元素 int index = indexs[0]; for(int j = 1 ; j < indexs.length ; j++) { //如果當前索引的值大於index索引的值的大小,則目前最大值的索引為當前索引 if(array[index] < array[indexs[j]]) { index = indexs[j]; } } return index; } //交換陣列中的兩個元素 public void swap(int[] array , int index1 , int index2) { int temp = array[index1]; array[index1] = array[index2]; array[index2] = temp; } }
本文概念部分轉自:
程式碼部分全由筆者實現。