堆排序原理及其实现----c++

 

老生常谈,开篇介绍,定义先行

堆排序:

堆排序(英语:Heapsort)是指利用这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质(即子结点的键值或索引总是小于(或者大于)它的父节点)。

实现

  • 最大堆调整(Max Heapify):将堆的末端子节点作调整,使得子节点永远小于父节点

  • 创建最大堆(Build Max Heap):将堆中的所有数据重新排序

  • 堆排序(HeapSort):移除位在第一个数据的根节点,并做最大堆调整的递归运算                                           (来自百度)

代码1.0(错误版本)

#include <iostream>
using namespace std;
//交换
void swap(int*a,int*b){
	int t=*a;
	*a=*b;
	*b=t;
} 
//最大堆调整(Max Heapify)
void MaxHeapify(int a[],int start,int end){
	int f=start;
	int lchild=2*f+1;
	int rchild=2*f+2;
	int son=lchild;
	
	while(lchild<=end){                             
		if((a[lchild]<a[rchild])&&(rchild<=end)){//1
			son=rchild;
		}
			
		if(a[f]>a[son]){
			return;
		}
		else {
			swap(a[f],a[son]); //2
			f=son;               //2
			son=2*f+1;          //2
			
		}
	}	
}

void heapsort(int a[],int len){
	//得到最大二叉堆(从最后一个父亲开始建),a[0]是最大的
	 for(int i=len/2-1;i>=0;i--)
         MaxHeapify(a, i, len - 1);
	 //整体排序·
	 for(int j=len-1;j>0;j--){
	//交换a[0]a[j]后,a[j]是最大的
            swap(a[0],a[j]);
        //保证堆的稳定大小,使得在0----j-1中a[j]依然最大
	    MaxHeapify(a,0,j-1);
	 } 
}

int main(){
int a[12]={3,4,5,6,7,1,2,3,8,9,10,0};
int len=sizeof(a)/sizeof(a[0]);
cout<<"before:"<<endl;
for(int i=0;i<len;i++){
	cout<<a[i]<<"  ";
}
cout<<endl;
heapsort(a,len);
cout<<"after:"<<endl;
for(int i=0;i<len;i++){
	cout<<a[i]<<"  ";
}
cout<<endl;
return 0;
} 

 

输出结果:

你没看错,就是没有输出。

错误原因:

没有输出,意味着程序在某一步骤死掉了,跳不出来,多为循环,这是就要写输出了来判断问题出现的位置

1.if((a[lchild]<a[rchild])&&(rchild<=end))值得注意的是&&会涉及短路规则,在逻辑上,要先判断它是否有右儿子,再比较出最大的儿子。出于规范,我将这两句话调换位置

2.可以看到,交换之后,对father变量进行了刷新,对最大儿子变量son也进行了刷新,但是,注意,我们的判断条件是rchild和lchild,这两个数据并未刷新,循环死掉;

代码2.0

#include <iostream>
using namespace std;
//交换
void swap(int*a,int*b){
	int t=*a;
	*a=*b;
	*b=t;
} 
//最大堆调整(Max Heapify)
void MaxHeapify(int a[],int start,int end){
	int f=start;
//	int lchild=2*f+1;
//	int rchild=2*f+2;
	int son=2*f+1;
	while(son<=end){
		if((son+1<=end)&&(a[son]<a[son+1])){
			son++;
		}
			
		if(a[f]>a[son]){
			return;
		}
		else {
			swap(a[f],a[son]);
			f=son;
			son=2*f+1; 
		
		}
	}	
}

void heapsort(int a[],int len){
	//得到最大二叉堆(从最后一个父亲开始建),a[0]是最大的
	 for(int i=len/2-1;i>=0;i--)
         MaxHeapify(a, i, len - 1);
	 //整体排序·
	 for(int j=len-1;j>0;j--){
	//交换a[0]a[j]后,a[j]是最大的,a[0]是在0---j最小的

            swap(a[0],a[j]);
        //保证堆的稳定大小,使得在0----j-1中a[0]最大
	    MaxHeapify(a,0,j-1);
	 } 
}


int main(){
int a[12]={3,4,5,6,7,1,2,3,8,9,10,0};
int len=sizeof(a)/sizeof(a[0]);
//int len=12;
cout<<"before:"<<endl;
for(int i=0;i<len;i++){
	cout<<a[i]<<"  ";
}
cout<<endl;
heapsort(a,len);
cout<<"after:"<<endl;
for(int i=0;i<len;i++){
	cout<<a[i]<<"  ";
}
cout<<endl;
return 0;
} 

结尾·放个彩蛋哦

推荐一个可视化的数据结构与算法是网站(emm动图演示排序,链表会更容易些吧,还提供代码运行处)

https://visualgo.net/en 

值得一乐 他的中文版缩写是zh(黑人问号脸,英文en)

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值