c语言实现堆构建,堆调整,堆排序——详细注释

#include <stdio.h> //关于最小堆,我们关心的是更小的那个节点

int h[101]; //用于存储数组
int n; //用于存储堆的大小

void swap(int x, int y)
{
	int temp;
	temp = h[x];
	h[x] = h[y];
	h[y] = temp;
}

void sift_down(int i) //传入需要向下调整的编号,然后按照最小堆,向下调整
{
	int t, flag = 0; //t用于存储,flag用于记录是否需要继续调整

	while (i * 2 <= n && flag == 0)
	{
		if (h[i] > h[i * 2]) //首先判断左节点,并用t记录较小节点的编号
			t = i * 2;
		else
			t = i;

		if (i * 2 + 1 <= n) //如果当前结点存在右儿子,再对右儿子进行讨论
			if (h[t] > h[i * 2 + 1]) //如果右儿子更小,更新较小结点的编号
				t = i * 2 + 1;

		if (t != i) //如果最小节点的编号不是自身,意味着子节点中有比父节点更小的
		{
			swap(t, i); //交换他们,为了构建新的最小堆
			i = t; //更新i为刚才于其交换的儿子的编号,便于接下来的向下调整
		}
		else
			flag = 1; //否则说明父节点已经比两个子节点都小, 不需要再进行调整了
	}
}

void sift_up(int i) // 传入一个需要向上调整的节点的编号
{
	int flag = 0; //用来标记结点是否需要向上调整
	if (i == 1) return; //如果是堆顶,就返回,不需要再调整
	while (i != 1) //不是堆顶且当前结点的值小于父节点就向上调整 (向上调整的函数,对于对的判断刚好与向上调整相反)
	{
		if (h[i] < h[i / 2]) //判断是否比父节点小
			swap(i, i / 2); //与父结点交换,向上调整
		else
			flag = 1; //表明当前节点的值小于父节点,不需要再调整了
		i = i / 2;//!!!更新编号,进而继续向上调整
	}
}

void creat() //创建堆
{
	for (int i = n / 2; i >= 1; i--) //从最后一个非叶节点开始,进行调整,当全部调整完了时,堆就构造好了
		sift_down(i);
}

int delete_min() //删除堆中最小的元素,也就是根节点,再重新调整最小堆
{
	int t = h[1]; //记录最小值,该值接下来要被覆盖,进而进行堆的调整
	h[1] = h[n--]; //将堆的最后一的元素赋值到堆顶,进而使堆的尺寸减1
	sift_down(1); //向下调整,构造新堆
	return t;
}

int main()
{
	int num;
	scanf("%d", &num);

	for (int i = 1; i <= num; i++)
		scanf("%d", &h[i]);

	n = num;
	creat();

	for (int i = 1; i < num; i++) // 每次将最小值删除并且打印, 实现堆排序。
		printf("%d ", delete_min());

	return 0;
}

参考于啊哈算法。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值