七大排序算法之堆排序

前言

堆排序也是一種非常重要的排序算法,但是在寫堆排序算法之前,需要對堆的概念有一定了解,簡單來說就是利用了大根堆和小根堆的特性,在大根堆中,堆頂的元素是整個堆元素中最大的,小根堆中,堆頂的元素是整個堆元素中最小的。

原理

其實原理簡單點說,就是利用大根堆小根堆的性質,那麼怎麼根據大根堆小根堆的性質來實現排序的效果呢?

第一步,建堆,如果爲升序,建大根堆,爲降序,建小根堆。怎麼將一個有序數組構建成一個堆呢?首先根據堆的特點,我們可以從堆的長度中心位置,也就是list.length/2的位置處,開始構建,然後獲取當前節點、當前節點的左節點、當前節點的右節點中的最大值,並將最大值置於父節點的位置,循環遍歷節點,直到爲0的位置,也就是遍歷到了堆頂的位置,至此,堆建立完畢。

時間複雜度

固定:爲n*logn

代碼

public class HeapSort {

	// 堆排序,利用大根堆/小根堆,堆頂元素最大/最小的特點,不斷和堆底元素進行交換,從而排序
	
	// 時間複雜度固定爲 n*Logn
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] arr = new int[] { 8, 5, 0, 7, 3, 1, 2 };
		System.out.println("排序前");
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + " ");
		}
		System.out.println();

		heapSort(arr);

		System.out.println("排序後");
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + " ");
		}
		System.out.println();
	}

	
	public static void HeapAdjust(int[] array, int parent, int length) {
		int child = 2 * parent + 1; // 先獲得左孩子
		while (child < length) {
			// 如果有右孩子結點,並且右孩子結點的值大於左孩子結點,則選取右孩子結點
			if (child + 1 < length && array[child] < array[child + 1]) {
				child++;
			}
			// 如果父結點的值已經大於孩子結點的值,則直接結束
			if (array[parent] >= array[child])
				// 跳出while循環體
				break;
			// 交換孩子節點和父節點的值
			int t;
			t = array[child];
			array[child] = array[parent];
			array[parent] = t;
			// 選取孩子結點的左孩子結點,繼續篩選下一個節點
			parent = child;
			child = 2 * child + 1;
		}

	}

	public static void heapSort(int[] list) {
		// 循環建立初始堆
		for (int i = list.length / 2; i >= 0; i--) {
			HeapAdjust(list, i, list.length - 1);
		}
		// 進行n-1次循環,完成排序
		for (int i = list.length - 1; i > 0; i--) {
			// 最後一個元素和第一元素進行交換
			int temp = list[i];
			list[i] = list[0];
			list[0] = temp;
			// 篩選 R[0] 結點,得到i-1個結點的堆
			HeapAdjust(list, 0, i);
		}
	}

}

下一篇:歸併排序

入口在此:點我學習歸併排序

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章