堆排序--java
阿新 • • 發佈:2018-12-03
堆是一種完全二叉樹,每個結點的值都大於或等於其左右孩子結點的值,稱為大頂堆;或者每個結點的值都小於或等於其左右孩子結點的值,稱為小頂堆。
先引入一下完全二叉樹的概念。
完全二叉樹 定義:完全二叉樹是由滿二叉樹而引出來的。對於深度為K的,有n個結點的二叉樹,當且僅當其每一個結點都與深度為K的滿二叉樹中編號從1至n的結點一一對應時稱之為完全二叉樹。 具有性質: 1) 深度為k的完全二叉樹,至少有2^(k-1)個節點,至多有2^k-1個節點。 2)樹高h=log2n + 1。 滿二叉樹 一棵深度為k,且有2^k-1個節點的樹是滿二叉樹。 另一種定義:除了葉結點外每一個結點都有左右子葉且葉子結點都處在 最底層的二叉樹。 這兩種定義是等價的 性質: 1) 如果一顆樹深度為h,最大層數為k,且深度與最大層數相同,即k=h; 2)它的葉子數是: 2^(h-1) 3) 第k層的結點數是: 2^(k-1) 4) 總結點數是: 2^k-1 (2的k次方減一) 5)總節點數一定是奇數。 6)樹高:h=log2(n+1)。
通俗的講:滿二叉樹,就是每一個父節點都有兩個葉子節點,每一層要不全是葉子節點,要不全是父節點(也即是說每一層都是滿節點的)。二完全二叉樹則是除了最後一層外,其他的層都是滿的,最後一層的葉子節點可以不滿,且最後一層的葉子節點從左到右,左邊沒滿,右邊不能有子節點(最後一層的葉子節點都靠左排列)。
堆排序(Heapsort)是指利用堆這種資料結構所設計的一種排序演算法。堆積是一個近似完全二叉樹的結構,並同時滿足堆積的性質:即子結點的鍵值或索引總是小於(或者大於)它的父節點。堆排序可以說是一種利用堆的概念來排序的選擇排序。分為兩種方法:大頂堆的生序排序,小頂堆的降序排序。
程式碼實現:
import java.util.Arrays; public class HeapSort { public int[] sort(int[] sourceArray) throws Exception { // 對 arr 進行拷貝,不改變引數內容 int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); int len = arr.length; buildMaxHeap(arr, len);//構建大頂堆 for (int i = len - 1; i > 0; i--) { swap(arr, 0, i);//使得陣列的最後一定為最大的數 len--; heapify(arr, 0, len);//重新整理大頂堆 } return arr; } /** * 構建大頂堆 * @param arr 資料陣列 * @param len 陣列長度 */ private void buildMaxHeap(int[] arr, int len) { //(int) Math.floor(len / 2) 向下取整,但是Math.floor()返回的型別是double,所以要強轉成int for (int i = (int) Math.floor(len / 2); i >= 0; i--) { heapify(arr, i, len); } } /** * 使得父節點大於等於左右子節點 * @param arr 陣列 * @param i 父節點位置 * @param len 陣列長度 */ private void heapify(int[] arr, int i, int len) { int left = 2 * i + 1; //左子節點位置 int right = 2 * i + 2;//右子節點位置 int largest = i; if (left < len && arr[left] > arr[largest]) { largest = left;//如果左子節點的值大於父節點位置的值,則替換largest } if (right < len && arr[right] > arr[largest]) { largest = right;//如果右子節點的值大於父節點位置的值,則替換largest } if (largest != i) { swap(arr, i, largest);//交換使得父節點的值比左右子節點的值都大。 heapify(arr, largest, len); } } /** * 交換函式 */ private void swap(int[] arr, int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } }
程式碼都寫有註釋,看懂應該不難,但是讓自己手寫一個,還真是得思路比較清晰才行,heapify()方法看著很簡單,確實很關鍵。細細品味。
測試main函式:
public class MainTest { public static void main(String[] args) throws Exception { HeapSort heap=new HeapSort(); int[] array={5,2,7,3,6,1,4}; array=heap.sort(array); for (int i=0;i<array.length;i++){ System.out.print(array[i]+","); } } }
結果:
1,2,3,4,5,6,7,