C语言数据结构堆排序

堆的概念

堆排序是一种树形选择排序,在排序过程中,将待排序的记录看成一颗完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系,在当前无序的序列中选出关键字最大或最小的记录。

堆分为大堆小堆,大堆就是根节点比所有结点要大的完全二叉树,小堆就是跟结点要比所有结点要小的完全二叉树。

堆的时间复杂度为O(n*logn),堆是一个不稳定排序

实现堆排序需要解决一下问题:

1.如何将一个无序序列建成一个堆

2.去掉堆顶元素,在堆顶元素改变之后,如何调整剩余元素成为一个新的堆。

 

void down(elem* a,int size, int parent)//向下调整
{
	assert(a);
	int child = 2 * parent + 1;
	//运用假设法,假设左孩子小
	while (child < size)//下标刚好停在数组末尾
	{
		if (child+1 < size && a[child + 1] < a[child])//如果该节点存在右节点并且child+1比child小时运行:child++
		{
			child++;//如果右孩子比左孩子大时让child+1,让较大的那个子节点与父节点进行比较
		}
		if (a[child] < a[parent])//如果子节点比父节点小,那就进行交换,然后继续向下调整
		{
			swap(&a[child], &a[parent]);
			parent = child;
			child = 2 * parent + 1;
		}
		else
		{
			break;
		}
	}
}

 

void sort2(elem* a, int x)//堆向下排序
{
	int i = 0;
	for (i = (x - 1 - 1) / 2; i >= 0; i--)
	{
		down(a,x,i);
	}
	int end = x - 1;
	while (end > 0)
	{
		swap(&a[0], &a[end]);
		down(a, end, 0);
		end--;
	}
}

降序需要建小堆,升序建大堆 ,这里作者的堆排序为降序,建小堆。

堆排序需要从第一个非叶子结点开始进行排序,最后一个结点的小标是x-1,所以其父亲的下标是(x-1-1)/2,第一个循环由此开始。

向下调整函数

down函数的作用使建小堆。

随后用down函数进行向下调整,down使用了假设法,开始时假设左孩子小。

使用while循环,循环结束时下标刚好停在数组末尾。

第一个if循环中的child+1<size是证明此结点是否存在右节点,且左孩子比右孩子小的是时候令child++使较大的结点与父亲结点进行比较。

如果子节点比父亲结点小,那就令二者进行交换,跟新二者的索引,随后继续向下调整。

就此小堆建造完成,解决第一个问题

while内容

到while循环时此时就建成了小堆。

第二个while循环使end到堆顶的下标时停下。此时交换第一个和最后一个的数据,此时最后一个元素就是最小的。

然后再进行向下调整排序,此时down的范围将排除最后一个元素,只从倒数第二个元素开始排序,此时最后一个元素的顺序已经固定了下来。

在while循环的作用下,小的数据不断被交换到数组后面,end--避免了以排好的数再次进行排序。

最后数组便排成了降序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值