堆排序

堆排序

堆排序(Heapsort)是指利用堆這種數據結構所設計的一種排序算法。堆積是一個近似完全二叉樹的結構,並同時滿足堆積的性質:即子結點的鍵值或索引總是小於(或者大於)它的父節點。堆排序可以說是一種利用堆的概念來排序的選擇排序。分爲兩種方法:

大頂堆:每個節點的值都大於或等於其子節點的值,在堆排序算法中用於升序排列;
小頂堆:每個節點的值都小於或等於其子節點的值,在堆排序算法中用於降序排列;
堆排序的平均時間複雜度爲 Ο(nlogn)

算法步驟

  1. 自底向上構建大(小)頂堆
  2. 把堆首(最大值)和堆尾互換
  3. 把堆的尺寸縮小 1,堆化(自頂向下)
  4. 重複步驟 2、3,直到堆的尺寸爲 1
  • 父節點與子節點關係:parent := (i - 1) / 2
  • 左節點與父節點關係:left := 2*i + 1
  • 右節點與父節點關係:right := 2*i + 2

動圖演示

在這裏插入圖片描述

go實現大頂堆排序

注意點

  1. 堆化:注意變量 左、右、最大值下標
  2. 建堆:利用堆化,從數組長度一半開始循環堆化
  3. 堆排序:首尾交換,縮減長度再堆化
//堆化,自頂向下
func heapify(arr []int, n int) {
	//左右子節點
	l := 2 * n + 1
	r := 2 * n + 2
	//最大值的下標
	max := n

	//與左右節點比較,max爲最大值的下標
	if l < len(arr) && arr[max] < arr[l] {
		max = l
	}

	if r < len(arr) && arr[max] < arr[r] {
		max = r
	}

	if max != n {
		//最大值放到父點上
		arr[max], arr[n] = arr[n], arr[max]
		//自頂向下繼續堆化
		heapify(arr, max)
	}
}

//構建大頂堆,自底向上
func BuildMaxHeap(arr []int) {
	for i := (len(arr) - 1)/2 ; i >= 0; i-- {
		heapify(arr, i)
	}
}
//堆排序
func HeapSort(arr []int)  {
	arrLen := len(arr)
	BuildMaxHeap(arr)
	//首尾交換,縮減長度再堆化
	for i := len(arr) - 1; i>0 ; i-- {
		arr[0], arr[i] = arr[i], arr[0]
		arrLen -= 1
		heapify(arr[:arrLen], 0)
	}
}

go實現小頂堆排序

//堆化,自頂向下
func heapify(arr []int, i int) {
	arrLen := len(arr)
	//左右子節點
	left := 2*i + 1
	right := 2*i + 2
	//最小值的下標
	min := i

	//與左右節點比較,min爲最大值的下標
	if left < arrLen && arr[left] < arr[min] {
		min = left
	}
	if right < arrLen && arr[right] < arr[min] {
		min = right
	}
	if min != i {
		//最小值放到父點上
		arr[i], arr[min] = arr[min], arr[i]
		//自頂向下繼續堆化
		heapify(arr, max)
	}
}

//構建大頂堆,自底向上
func buildMaxHeap(arr []int) {
	arrLen := len(arr)
	for i := (arrLen - 1) / 2; i >= 0; i-- {
		heapify(arr, i)
	}
}

//堆排序
func heapSort(arr []int) {
	arrLen := len(arr)
	buildMaxHeap(arr)
	//首尾交換
	for i := arrLen - 1; i > 0; i-- {
		arr[0], arr[i] = arr[i], arr[0]
		arrLen -= 1
		heapify(arr[:arrLen], 0)
	}
}
發佈了322 篇原創文章 · 獲贊 163 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章