堆排序及优先队列

堆排序的时间复杂度为o(nlogn)不需要额外空间
堆可以看成一个存储在数组中的近似完全二叉树结构。
下标为(0…n)父节点下标为p则左孩子下标为2p+1
,右孩子下标为2
p+2。其中在最大(小)堆中,父节点比两个孩子节点大(小)。在这里仅讨论最大堆。
对堆的操作:

void MaxHeapify(int *numSequence ,int i,int lenth);//最大堆的维护 
void Build_MaxHeap(int *numSequence,int lenth);//建造最大堆 
void Heap_Insert(int *numSequence,int *lenth,int x);//向最大堆中插入元素 
void Heap_Sort(int *numSequence,int lenth);//堆排序
int Heap_Pop(int *numSequence,int *lenth);//弹出
int Maximum(int *numSequence)//返回最大值 
 

堆的维护:维护某一个节点,使以它以及它的子节点为根节点的堆都为最大堆,递归调用自己(前提:以子节点为跟节点的堆都为最大堆)
建造最大堆:从后往前遍历每个非叶节点,对其调用堆维护。
堆的插入:将要插入的元素放在序列的尾部,再不断与父节点比较,若大于父节点,则与父节点交换,否则已经是一个最大堆。
堆排序:首先建造一个最大堆,然后不断将下表为0的元素与序列最后一个元素交换位置,堆的长度减一,再对下标为0的节点调用堆的维护。重复此操作,直到堆的长度小于等于1.
弹出:弹出堆的根节点的元素,lenth-1,并将最后的元素移到跟节点,调用堆的维护。
这里是C语言实现:

void MaxHeapify(int *numSequence ,int i,int lenth){//维护堆
  int left ,right,maxchild;
  if(lenth/2-1<i)return;//若为叶节点直接返回 
  else{
  	left=2*i+1,right=2*i+2,maxchild=left;
  	if(right<lenth)maxchild=cmp(numSequence[right],numSequence[left])>0?right:left;
  	if(cmp(numSequence[i],numSequence[maxchild])<0){
  		swap(i,maxchild,numSequence);
  		MaxHeapify(numSequence,maxchild,lenth);
	  }
  } 	
 }
 void Build_MaxHeap(int *numSequence,int lenth){
 	int i;
 	for(i=lenth/2-1;i>=0;i--){
 		MaxHeapify(numSequence,i,lenth);
	 }
 }
 void Heap_Insert(int *numSequence,int *lenth,int x){
 	numSequence[(*lenth)++]=x;
 	int i,parent,child,tmp;
 	child=*lenth-1;
 	parent=child/2-1;
 	while(child!=0){
 		if(cmp(numSequence[child],numSequence[parent])>0){
 			swap(child,parent,numSequence);
 			child=parent,parent=child/2-1;
		 }
		 else break;
		 
	 }
 	
 }
 void Heap_Sort(int *numSequence,int lenth){
 	Build_MaxHeap(numSequence,lenth);
 	for(;lenth>1;){
 		swap(0,lenth-1,numSequence);
 		MaxHeapify(numSequence,0,--lenth); 
 		
	 }
 }
 int Heap_Pop(int *numSequence,int *lenth){
 	swap(0,*lenth-1,numSequence);
 	*lenth--;
 	MaxHeapify(numSequence,0,*lenth);
 }
 int Maximum(int *numSequence){
 return numSequence[0];
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值