1. 程式人生 > 實用技巧 >Java資料結構(十一)—— 堆及堆排序

Java資料結構(十一)—— 堆及堆排序

堆基本介紹

  • 堆排序是利用堆這種資料結構而設計的一種排序演算法,堆排序是一種選擇排序,最壞,最好,平均時間複雜度都是O(nlogn),不穩定的排序

  • 堆是具有以下性質的完全二叉樹:每個節點的值都大於或等於其左右孩子節點的值稱為大頂堆

  • 小於或等於左右孩子節點的值稱為小頂堆

堆排序

基本思想

  1. 將待排序的序列構造成一個大頂堆(陣列)

  2. 此時 ,整個序列的最大值就是堆頂的根節點

  3. 將其與末尾元素進行交換,此時末尾為最大值

  4. 然後將剩餘n-1個元素重新構造成一個堆,這樣就會得到n個元素的次小值。如此反覆執行便能得到一個有序序列

基本步驟

  1. 構造初始堆,順序存放

  2. 從最後一個非葉子節點:arr.length/2-1,開始,從左至右,從下至上進行調整

  3. 找到第二個非葉子節點,比較其與子節點的大小進行交換

  4. 這會導致其交換子樹的順序混亂則繼續向下交換

  5. 堆頂出堆,針對剩餘元素重複上列步驟

程式碼實現

package com.why.tree;

import java.util.Arrays;
import java.util.jar.JarEntry;

/**
* @Description TODO 堆排序
* @Author why
* @Date 2020/11/26 18:05
* Version 1.0
**/
public class HeapSort {
public static void main(String[] args) {
int[] arr = {4,6,8,5,9};
heapSort(arr);
}

/**
* 堆排序
* @param arr
*/
public static void heapSort(int[] arr){
int temp = 0;
//調整成大頂堆
for (int i = arr.length/2 - 1; i >= 0 ; i--) {
adjustHeap(arr,i,arr.length);
}
//將堆頂元素與末尾元素交換,將最大元素沉到陣列末端
for (int i = arr.length - 1; i > 0; i--) {
//交換
temp = arr[i];
arr[i] = arr[0];
arr[0] = temp;
adjustHeap(arr,0, i);
}
System.out.println(Arrays.toString(arr));
}

/**
* 將陣列(二叉樹)調整為大頂堆
* 完成將i對應的的非葉子節點調整成大頂堆
* 自下向上調整
* @param arr 待調整的陣列
* @param i 表示非葉子節點在陣列中的索引
* @param lengt 表示對多少個元素進行調整,lengt逐漸減小
*/
public static void adjustHeap(int[] arr,int i,int lengt){
//取出當前的值,儲存至臨時變數
int temp = arr[i];
//開始調整
//j = i * 2 + 1,j是i節點的左子節點
for (int j = i * 2 + 1; j < lengt; j = j * 2 + 1) {
if(j + 1< lengt &&arr[j] < arr[j+1]){//左子節點小於右子節點
j++;//j指向右子節點
}
if (arr[j] > temp){//如果子節點大於父節點
arr[i] = arr[j];//把子節點較大的值與父節點交換
i = j;//i指向j繼續迴圈比較
}else {
break;
}
}
//for迴圈結束後已將以i為父節點的的樹的的最大值放到了堆頂(區域性)
arr[i] = temp;//將temp賦值放到最後的位置
}
}