Java实现堆排序及详细图解
文章目錄
- 堆排序
- 前言
- 實(shí)現(xiàn)步驟
- 代碼實(shí)現(xiàn)
堆排序
前言
堆排序(HeapSort)是指利用堆這種數(shù)據(jù)結(jié)構(gòu)所設(shè)計(jì)的一種排序算法。堆積是一個(gè)近似于完全二叉樹(shù)的結(jié)構(gòu),同時(shí)滿足子節(jié)點(diǎn)的鍵值總是小于(或者大于)其父節(jié)點(diǎn)。
每個(gè)節(jié)點(diǎn)的值都大于或者等于其左右子節(jié)點(diǎn)的值,稱(chēng)為大頂堆;或者每個(gè)節(jié)點(diǎn)的值都小于或者等于其左右子節(jié)點(diǎn)的值,稱(chēng)為小頂堆。
對(duì)堆中的節(jié)點(diǎn)按層進(jìn)行編號(hào),將這種邏輯結(jié)構(gòu)映射到數(shù)組如下圖所示:
該數(shù)組從邏輯上講就是一個(gè)堆結(jié)構(gòu),并且有以下特點(diǎn):
大頂堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]
小頂堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]
綜上,堆排序的基本思想就是將待排序的序列構(gòu)建成一個(gè)大頂堆,此時(shí)整個(gè)序列最大值就是堆頂?shù)母?jié)點(diǎn)。將其與末尾元素交換,此時(shí)末尾元素就成為最大值。然后將剩余n-1個(gè)元素重新構(gòu)造成一個(gè)堆,這樣會(huì)得到n個(gè)元素中的次小值,也就是n-1個(gè)元素中的最大值,并將其放置末尾,并如此反復(fù),就能得到一個(gè)有序序列。
實(shí)現(xiàn)步驟
步驟一:構(gòu)造初始堆,將給定無(wú)序序列構(gòu)造成一個(gè)大頂堆
假定無(wú)序序列結(jié)構(gòu)如下
此時(shí)從最后一個(gè)非葉子節(jié)點(diǎn)[6]開(kāi)始,葉結(jié)點(diǎn)不用調(diào)整,從左至右,從上至下進(jìn)行調(diào)整。
找到第二個(gè)非葉子節(jié)點(diǎn)[4],由于{4,8,9}中9元素最大,4和9交換。
此時(shí),交換導(dǎo)致了子樹(shù){4,5,6}結(jié)構(gòu)混亂,繼續(xù)調(diào)整,現(xiàn)在6元素最大,交換4和6
步驟二:將堆頂元素與末尾元素進(jìn)行交換,使末尾元素最大,然后繼續(xù)調(diào)整堆,再將堆頂元素與末尾元素交換,如此反復(fù)重建和交換。
將堆頂元素9和末尾元素4進(jìn)行交換
重新調(diào)整結(jié)構(gòu),使其繼續(xù)滿足堆定義
再將堆頂元素8與末尾元素5進(jìn)行交換,得到第二大元素8
后續(xù)過(guò)程,繼續(xù)進(jìn)行調(diào)整,交換,如此反復(fù)調(diào)整,最終即可整個(gè)序列有序。
堆排序算法的基本思路總結(jié):
- 將無(wú)序序列建成一個(gè)堆,根據(jù)升降序需求選擇大頂堆和小頂堆。
- 將堆頂元素與末尾元素交換,將最大元素沉到數(shù)組末端。
- 重新調(diào)整,使其重新滿足堆定義,然后繼續(xù)交換堆頂元素和當(dāng)前末尾元素,反復(fù)執(zhí)行調(diào)整和交換,直至整個(gè)序列有序。
代碼實(shí)現(xiàn)
public static void heapSort(int[] array) {//從倒數(shù)第一個(gè)非葉子節(jié)點(diǎn)開(kāi)始for (int i = array.length/2 - 1; i>=0; i--){//從第一天非葉子節(jié)點(diǎn)從下至上,從左至右調(diào)整結(jié)構(gòu)adjustHeap(array,i, array.length);}//將堆頂元素與末尾元素交換 將最大元素沉到數(shù)組末尾 + 重新調(diào)整堆結(jié)構(gòu)for (int i = array.length - 1; i > 0 ; i--){//交換堆頂元素和末尾元素swap(array,0,i);//交換后的末尾元素忽略(j--) 不再參與堆結(jié)構(gòu)的調(diào)整//重新調(diào)整堆結(jié)構(gòu)adjustHeap(array,0,i);}}private static void swap(int[] array, int start, int end) {int temp = array[start];array[start] = array[end];array[end] = temp; }public static void adjustHeap(int[] array,int index,int length) {//取出當(dāng)前元素int temp = array[index];//i節(jié)點(diǎn)是index節(jié)點(diǎn)的左子節(jié)點(diǎn)for (int i = 2 * index + 1; i < length; i = 2 * i + 1){//表明左子節(jié)點(diǎn)小于右子節(jié)點(diǎn)if (i+1 < length && array[i] < array[i+1]){//將指針移至較大節(jié)點(diǎn)i++;}//如果子節(jié)點(diǎn)大于父節(jié)點(diǎn)if (array[i] > temp){//將較大值賦給當(dāng)前節(jié)點(diǎn)array[index] = array[i];//指針移向子節(jié)點(diǎn)index = i;}else{break;}}//循環(huán)結(jié)束,已經(jīng)將最大值放在了堆頂//將temp值放到最終的位置array[index] = temp;}public static void main(String[] args) {//升序int[] array = {4,6,8,78,13,19,1,5,9,};System.out.println("排序前=>"+ Arrays.toString(array));heapSort(array);System.out.println("排序后=>"+Arrays.toString(array)); }輸出結(jié)果
排序前=>[4, 6, 8, 78, 13, 19, 1, 5, 9] 排序后=>[1, 4, 5, 6, 8, 9, 13, 19, 78]以上。
如有不足或錯(cuò)誤歡迎評(píng)論指正。
總結(jié)
以上是生活随笔為你收集整理的Java实现堆排序及详细图解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Java实现前中后序线索化二叉树以及遍历
- 下一篇: 深入学习Redis