C语言实现二叉堆

自己写了下二叉堆的一些操作以及堆排序
主函数就是下面这样,每个操作都是一个独立的函数,方便查看

然后我的是以最大堆为例的,最小堆操作几乎一样,就是大于小于号的修改
然后我喜欢下标从1开始,就把a[0]给废掉了,这样子可读性也强些

从0开始的也差不多,就是对于编号为K的结点,儿子结点编号分别为Kx2+1和Kx2+2(这里的"X"是乘号的意思,好像写博客的时候米字符和加粗操作有重合地方)

然后注意upAdjust和downAdjust里面那些结点数据的上浮和下沉其实是用了直接插入排序的思想,从那个temp记录初始的数据应该可以看出,这样比交换好一点

int main()
{
	Create();//构建最大堆 
	Delete();//删除堆顶元素 
	Insert();//插入一个元素
	Heap_Sort();//堆排序,升序 
}

无序堆构造最大堆

void PRINT(int *a,int N)
{
	for(int i=1;i<=N;i++)
	{
		printf("%d ",a[i]);	
	}
	printf("\n");	
}

void downAdjust(int *a,int N,int i){
	int fa_index,child_index,temp;
	
	fa_index=i;
	child_index=fa_index*2;
	temp=a[fa_index];//先记录
	while(child_index<=N)
	{
		if(child_index+1<=N)//如果有右孩子结点
		{
			if(a[child_index+1]>a[child_index])//
			{
				child_index++;
			}
		}//得到最大子结点的小标 
		if(temp>a[child_index]){
			break;
		}
		a[fa_index]=a[child_index];
		fa_index=child_index;
		child_index=child_index*2;
	}
	a[fa_index]=temp;
}

void Create()
{
	int N=10;
	int a[N+1]={0,14,9,6,13,21,10,16,17,2,12};//构造用的无序数组 
	int i;
	for(i=N/2;i;i--)//从编号最大的有子结点的结点开始到结点1
	{
		downAdjust(a,N,i);//对每个结点进行下沉
	}
	printf("构造出的最大堆为:\n");
	PRINT(a,N);
}

最大堆的删除顶结点操作

//删除和构造都是用的下沉调试操作
void PRINT(int *a,int N)
{
	for(int i=1;i<=N;i++)
	{
		printf("%d ",a[i]);	
	}
	printf("\n");	
}

void downAdjust(int *a,int N,int i){
	int fa_index,child_index,temp;
	
	fa_index=i;
	child_index=fa_index*2;
	temp=a[fa_index];//先记录
	while(child_index<=N)
	{
		if(child_index+1<=N)//如果有右孩子结点
		{
			if(a[child_index+1]>a[child_index])//
			{
				child_index++;
			}
		}//得到最大子结点的小标 
		if(temp>a[child_index]){
			break;
		}
		a[fa_index]=a[child_index];
		fa_index=child_index;
		child_index=child_index*2;
	}
	a[fa_index]=temp;
}

void Delete()
{
	int N=10;
	int a[N+1]={0,21,17,16,14,12,10,6,13,2,9};//已建好的最大堆 
	a[1]=a[N--];//把结点1用最后一个结点替换掉,并且N要减1
	downAdjust(a,N,1);//把结点1下沉
	printf("删除后的最大堆为:\n");
	PRINT(a,N);
}

最大堆的插入操作

void PRINT(int *a,int N)
{
	for(int i=1;i<=N;i++)
	{
		printf("%d ",a[i]);	
	}
	printf("\n");	
}

//插入是把要插入的数放在数组末尾,再向上调试
void upAdjust(int *a,int N)
{
	int index=N;
	int fa_index=N/2;
	int temp=a[index];
	while(fa_index)
	{
		if(temp<a[fa_index])
		{
			break;
		}
		a[index]=a[fa_index];
		index=fa_index;
		fa_index=index/2;
	}	
	a[index]=temp;//这里也用了插入排序的思想
}

void Insert()
{
	int N=10;
	int a[N+2]={0,21,17,16,14,12,10,6,13,2,9};//已建好的最大堆 
	int tar=23;//可以修改
	a[++N]=tar;//记得N要加一
	upAdjust(a,N);
	printf("插入%d后的最大堆为:\n",tar);
	PRINT(a,N);
}

堆排序

void downAdjust(int *a,int N,int i){
	int fa_index,child_index,temp;
	fa_index=i;
	child_index=fa_index*2;
	temp=a[fa_index];
	while(child_index<=N)
	{
		if(child_index+1<=N)
		{
			if(a[child_index+1]>a[child_index])
			{
				child_index++;
			}
		}//得到最大儿子结点的小标 
		if(temp>a[child_index]){
			break;
		}
		a[fa_index]=a[child_index];
		fa_index=child_index;
		child_index=child_index*2;
	}
	a[fa_index]=temp;
}

void Heap_Sort()
{
	int N=10,size=N;
	int a[N+1]={0,21,17,16,14,12,10,6,13,2,9};//已建好的最大堆
	//这里我偷懒了,直接用的最大堆,如果一开始堆是无序的,要先构建最大堆
	int temp;
	while(size)
	{
		int temp=a[size];
		a[size]=a[1];
		a[1]=temp;//这三行就是交换a[1]和a[N],这样可以让每次a[N]都是最大的
		printf("%d ",a[size--]);//记得减一
		downAdjust(a,size,1);//每次把那两个结点交换后再把堆变为最大堆,始终保持堆顶元素最大
	}
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值