1. 程式人生 > >排序演算法之堆排序演算法的實現

排序演算法之堆排序演算法的實現

在做一份筆試題時,發現對堆排序演算法還不甚瞭解,所以趕緊了解了一下相關思想和概念,並嘗試自身實現了一下,在這附上概念思想以及程式碼的實現。

堆排序:利用堆資料結構而設計的一種排序演算法,堆排序是一種選擇排序,它的最壞,最好,平均時間複雜度均為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;
		}
	}

本文概念部分轉自:

程式碼部分全由筆者實現。