堆排序(大顶堆)

最近在看算法导论,顺便把里面的程序都实现下,先拿堆排序来练练手吧。

首先介绍下堆调整,堆是一种数据结构,是一种完全二叉树(不一定是满二叉树),所以根节点与叶子节点满足关系如下:根节点下标为i,左叶子为下标2*i,右叶子下标为2*i+1,当然这里我们用数组来对堆进行存储。堆的子树必须满足如下关系,根节点大于左子树且大于右子树。

堆调整的方法如下,检测根节点是否为叶子节点,是退出,否调出子树中最大的值作为根节点,并对受影响的叶子节点进行递归调整。代码如下:

int modify(int length,int i,int array_sort[])
{
	int max = i,r,l;
	r = right(i);
	l = left(i);
	if(i > length/2) return 0;
	if(l <= length && array_sort[l] > array_sort[max])
		max = l;
    if(r <= length && array_sort[r] > array_sort[max])
		max = r;
	if(max != i)
	{
		swap(array_sort[max],array_sort[i]);
		modify(length,max,array_sort);
	}
	
}

之后介绍建立堆,给定数组123456,得到堆,对得到的堆进行调整可以从第一个非叶子节点进行对调整,直到调整到根节点。代码如下:

void create_heap(int array_sort[],int length)
{
	int i;
	for(i = length/2;i >= 1; i--)
	{
		modify(length,i,array_sort);
	}
}
最后介绍下堆排序的过程,首先对给定的数组建立堆,建立完成之后,堆顶必为最大的值,将堆顶与堆尾交换(即将堆定移除堆),之后重新对堆进行调整(堆长度减一),

之后再交换再调整,直到堆中只有一个数为止,全部代码如下:

#include<iostream>
#include<stdio.h>
#define left(x) (x)<<1
#define right(x) ((x)<<1)+1
#define LENGTH 10000
void swap(int &a,int &b)
{
	int temp;
	temp = a;
	a = b;
	b = temp;
}
int modify(int length,int i,int array_sort[])
{
	int max = i,r,l;
	r = right(i);
	l = left(i);
	if(i > length/2) return 0;
	if(l <= length && array_sort[l] > array_sort[max])
		max = l;
    if(r <= length && array_sort[r] > array_sort[max])
		max = r;
	if(max != i)
	{
		swap(array_sort[max],array_sort[i]);
		modify(length,max,array_sort);
	}
	
}
void create_heap(int array_sort[],int length)
{
	int i;
	for(i = length/2;i >= 1; i--)
	{
		modify(length,i,array_sort);
	}
}
void heap_sort(int array_sort[],int length)
{
	create_heap(array_sort,length);
	for(int i = length;i >= 1; i--)
	{
            swap(array_sort[1],array_sort[i]);
            modify(i-1,1,array_sort);
    }
}
int main()
{
	int length,i,array_sort[LENGTH];
	printf("intput length of the array you want to sort\n");
	scanf("%d",&length);
	printf("int put the array now\n");
	for(i = 1;i <= length; i++)
		scanf("%d",&array_sort[i]);
	heap_sort(array_sort,length);
	for(i = 1;i <=length;i++)
		printf("%d ",array_sort[i]);
	system("pause");
	return 0;

}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值