堆排序的实现--建堆、调整、排序

堆排序是一种树形选择的排序算法,在排序过程中将数组看作是一棵完全二叉树。但其实它是顺序存储的结构,这里我们实现的是大根堆的建堆算法。

堆排序:建大根堆-->输出堆顶元素(和堆底元素交换)-->整理将其重新整理成为堆

(1)大根堆(堆顶元素大于或等于其对应的子节点)

  • L[i]>=L[2*i]
  • L[i]>=L[2*i+1] 

(2)小根堆(堆顶元素小于或等于其对应的子节点)

  • L[i]<=L[2*i]
  • L[i]<=L[2*i+1]

一、构建初始大根堆

构建大顶堆的过程就是一个反复筛选的过程,从第一个非叶子结点开始,调用调整筛选的算法,逐步向上进行调整,直至堆顶元素。

调整算法:使用a[0]来暂存需要调整的元素值,从该节点的左孩子节点出发,比较左孩子结点与右孩子结点的值大小,选出值较大的结点。若该节点小于父节点的值,则不用进行调整;若该节点大于父节点的值,则将其值赋值给父节点,调整结点的下标值。在这一过程中,由于交换后可能会破坏掉刚建好的子堆,因此,需要使用循环,依次检查其子堆是否还满足大顶堆。i=i*2

实现代码

//堆排序
//建堆过程
#include<iostream>
using namespace std;
typedef int Elemtype;
void Build_Heap(Elemtype a[],int len);
void AdjustDown(Elemtype a[],int k,int len);
void Heap_Sort(Elemtype a[],int len);
void Build_Heap(Elemtype a[],int len){//建大顶堆过程,从第一个非叶节点开始,逐步进行向上的调整
	int i;
	for(i=len/2;i>0;i-- ){
	  AdjustDown(a,i,len);
	}
}
void AdjustDown(Elemtype a[],int k,int len){
	a[0]=a[k];//在数组中,我们使用a[0]来暂存需要调整的元素
	int i;
	for(i=2*k;i<=len;i*=2){//从该节点的左孩子出发,进行调整比较
	  if(i<len && a[i]<a[i+1])
           i++;//选取孩子节点中较大的结点
	  if(a[0]>=a[i]) //父节点已经大于子节点,不用交换
		  break;
	  else{//子节点大于父节点
	        a[k]=a[i];
			k=i;
	  }
	}
	  a[k]=a[0];
}
void Heap_Sort(Elemtype a[],int len)
{
	Build_Heap(a,len);
	for(int i=len;i>1;i--){//将堆顶与堆尾元素交换
	  swap(a[i],a[1]);
	  AdjustDown(a,1,i-1);//输出a[i],继续调整至大顶堆
	}
}
int main(){
	Elemtype a[8]={0,2,3,7,5,4,1,6};//注意在这里a[0]是暂存元素的,所以输入的时候存放一个0值
	Heap_Sort(a,7);
	for(int j=1;j<=7;j++){
	 cout<<a[j]<<" ";
	}
	cout<<endl;
	system("pause");
	return 0;
}

 

需要注意的是:这里我们使用了a[0]来暂存需要调整的元素,所以a[0]的值我们赋予其为0 

猜你喜欢

转载自blog.csdn.net/qq_40170007/article/details/88076207
今日推荐