手写堆排序

手写堆排序

摘要:本文记录使用go语言实现堆排序

堆的构建

  • 堆性质: 对于每个小堆,父节点与两个子节点比较,父节点比左子节点大,也比右子节点大。

有五个数: 1,2,3,4,5 分别进行入栈。过程如下

(1) 堆为空时,元素1 放入堆
在这里插入图片描述
(2) 取出元素2,挂到元素1后面


(3) 比较元素2,与父元素元素1,由于元素2 比 元素1 大,所以两个元素交换
在这里插入图片描述

(4) 元素3 先放入堆最后

(5) 元素3 比父节点大,与父节点交换

在这里插入图片描述
(6) 元素4 放到堆最后

(6) 元素4 比父节点你先把给的和反正都吃了元素1 大,所以把元素4 与 元素1 交换
在这里插入图片描述

(7) 元素4 比父节点元素3 大,所以把元素4 与 元素3我 交换
在这里插入图片描述

(8) 同理,元素5 先放入堆最后,再分别与父节点比较,直到达到堆性质。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

代码实现

package main

import "fmt"

// heapify 将父节点与子节点比较,并将最大值放到父节点(用于实现大顶堆)
func heapify(arr []int, n, i int) {
	if i >= n {
		// 递归退出条件
		return
	}
	// 找出最大的
	var prarent = i
	var max = prarent
	var c1 = prarent*2 + 1
	var c2 = prarent*2 + 2
	if c1 < n && arr[c1] > arr[max] {
		max = c1
	}
	if c2 < n && arr[c2] > arr[max] {
		max = c2
	}
	// 如果最大节点不是父节点,则最大的节点与父节点交换
	if max != prarent {
		arr[max], arr[i] = arr[i], arr[max]
		// 递归的进行 heapify
		heapify(arr, n, max)
	}

}

// heapInit 遍历依次heapify
func heapInit(arr []int, n int) {
	for i := 0; i < n; i++ {
		heapify(arr, n, i)
	}
}

// 利用堆实现排序
func heapSort(heapTree []int) {
	if len(heapTree) == 0 {
		return
	}
	var heapSize = len(heapTree)
	for heapSize > 0 {
		// 将堆顶元素放到最后
		heapTree[0], heapTree[heapSize-1] = heapTree[heapSize-1], heapTree[0]
		heapSize--

		// 对堆顶元素执行heapify
		heapify(heapTree, heapSize, 0)
	}
}

func main() {
	arr := []int{2, 1, 10, 3, 5, 4}

	heapInit(arr, 6)
	fmt.Println(arr) // [10 5 4 3 1 2]

	heapSort(arr)

	fmt.Println(arr) // 1 2 3 4 5 10

	arr = []int{3, 3, 4, 2, 1}

	heapInit(arr, 5)
	fmt.Println(arr)

	heapSort(arr) // [4 3 3 2 1]

	fmt.Println(arr) // 1 2 3 3 4

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SRExianxian

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值