时间复杂度为O(nlogn),思路就是从最后一个非叶结点开始,依次往回遍历每个结点,将以该结点为根的子树建立成大根堆,直到遍历到整棵完全二叉树的根结点时为止,此时整棵树为大根堆。

以当前结点为根的子树建立大根堆:

//向下调整,将该结点的子树变成大根堆 
void AdjustDown(int A[],int k,int len){	//k为根结点编号,len为数组长度 
	int i,j;
	A[0]=A[k];
	for(j=2*k;j<=len;j*=2){
		if(j<len&&A[j]<A[j+1])	//右孩子较大
			j++;
		if(A[0]<A[j]){
			A[k]=A[j];
			k=j; 
		}
		else break;
	}
	A[k]=A[0];
}

堆排序算法:

//堆排序算法 
void HeapSort(int A[],int len){
	int i,temp;
	for(i=len/2;i>=1;i--)	//建立初始大根堆
		AdjustDown(A[],i,len);	//从len/2到1,反复调整堆
	for(i=len;i>1;i--){
		temp=A[1];
		A[1]=A[i];
		A[i]=temp;	//把最大的元素放到了最后面,最终排序结果为由小到大
		AdjustDown(A[],1,i-1);	//把剩余i-1个元素整理成堆
	}
}

这样排序的结果为由小到大! 

如果插入元素的话,直接插入到最后的位置,然后将插入的元素向上调整,直到整棵树再次变成大根堆时为止!

向上调整的代码:

//插入元素到最后位置,需要向上调整建立大根堆 
void AdjustUp(int A[],int len){
	A[0]=A[len];
	int i=len/2,j=len;
	while(i>0&&A[i]<A[0]){
		A[j]=A[i];	//双亲结点下调
		j=i;
		i/=2;	//继续向上比较 
	}
	A[j]=A[0]; 
}