小白进阶之堆排序

堆排序与归并排序一样,但不同于插入排序的是堆排序的时间复杂度为O(nlgn)。而与插入排序相同,但不同于归并排序的是堆排序同样具有空间原址性:任何时候都只需要常数个额外的元素空间存储临时数据。堆分为最大堆和最小堆。

最大堆性质是指除了跟以外的所有结点i都满足:a[parent(i)]>=a[i];

最小堆性质是指除了跟以外的所有结点都满足:a[parent(i)]<=a[i]。

此处堆排序使用的是最大堆。最小堆比较适合构造优先队列。

下面是代码:

“heapsort.h”

#include<stdio.h>
#include<stdlib.h>
int parent(int i);//得到父结点
int left(int i);//得到左孩子下标
int right(int i);//得到右孩子下标
void maxHeapify(int *a,int n,int i);//维护堆性质:给定一个数组a和一个下标i,假定i的左右子树都是最大堆,通过让a[i]值在最大堆中逐级下降,
                                    //从而使以i为根节点的子树重新遵循最大堆的性质
void buildMaxHeap(int *a,int n);//建堆
void heapsort(int *a,int n);//堆排序
"heapsort.cpp"

#include"heapsort.h"
int parent(int i){
	int j=i/2;
	return j;
}
int left(int i){
	return 2*i;
}
int right(int i){
	return 2*i+1;
}
void maxHeapify(int *a,int n,int i){
	int l,r,max,t;
	l=left(i);
	r=right(i);
	if((l<=n)&&(a[l-1]>a[i-1]))
		max=l;
	else max=i;
	if((r<=n)&&(a[r-1]>a[max-1]))
		max=r;
	if(max!=i){
		t=a[i-1];
		a[i-1]=a[max-1];
		a[max-1]=t;
		maxHeapify(a,n,max);
	}
}
void buildMaxHeap(int *a,int n){
	int i;
	for(i=n/2;i>=0;i--){
		maxHeapify(a,n,i+1);
	}
	for(i=0;i<n;i++){
		printf("%d ",a[i]);
	}
}
void heapsort(int *a,int n){
	buildMaxHeap(a,n);
	int i,t;
	for(i=n-1;i>0;i--){
		t=a[0];
		a[0]=a[i];
		a[i]=t;
		n=n-1;
		maxHeapify(a,n,1);
	}
}
"main.cpp"

#include"heapsort.h"
int main(){
	int *a,n,i;
	printf("Please input the number of array:\n");
	scanf("%d",&n);
	a=(int *)malloc(sizeof(int)*n);
	printf("Please input the array:\n");
	for(i=0;i<n;i++)
		scanf("%d",&a[i]);
	heapsort(a,n);
	printf("\n");
	for(i=0;i<n;i++)
		printf("%d ",a[i]);
	system("pause");
	return 0;
}
刚开始写heapsort函数的时候,虽然一次编译通过,但是后来我想要查看堆的时候发现建堆建的不正确。

原因是C语言中数组是从0开始的,而建堆的伪码是从1开始的。0的左右子树经过计算分别是0和1,这就导致了错误。

我做的修改就是在调用函数时,对实参做一些修改,加1或者减1,这样建的堆就是正确的啦~


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值