堆排序:三角堆的叠加

按自己的理解,可以分成很多个三角堆叠加。那么堆的调整就是对三角堆的调整:把最大值或最小值交换到三角堆的顶部,再递归。

1-堆的基本结构

一、最基本的三角堆调整递归函数:

/*************三角堆调整******************/
/*
1、调整为三角节点,顶部为最大值
2、递归:向关键值较大的孩子节点向下进行
*/
/*
cin:数组a[],需要调整的三角节点顶部:i,数组总长:size。
*/
void HeapAdjust(int *a,int i,int size)  //调整堆 从i-size间的调整
{    
	int lchild=2*i;       //i的左孩子节点序号     
	int rchild=2*i+1;     //i的右孩子节点序号     
	int tmp=i;            //临时变量     
    //先定位左右孩子中数值较大者,再交换上来
	if(lchild<=size&&a[lchild]>a[tmp])        
	{           
		tmp=lchild;        
	}            
	if(rchild<=size&&a[rchild]>a[tmp])       
	{            
		tmp=rchild;        
	}  
	//判定找到孩子节点,则把孩子节点交换到顶部
	if(tmp!=i)
	{           
		swap(a[i],a[tmp]);  
		//继续调整对应的孩子节点
		HeapAdjust(a,tmp,size);    //避免调整之后以tmp为父节点的子树不是堆         
	}        
}

二、建立堆:多个三角堆叠加起来。

思想:把最大值逐步交换到顶部,建立大顶堆,且每个子节点都是大顶堆***/

1、从下往上逐渐调整三角堆,自底而上地调用HeapAdjust来将一个数组a[1..size]变成一个最大堆

/*
**从最下面的三角堆开始调整,即非叶子节点的最大序号处开始往上调整***
**cin:数组a,数组大小
*/

void BuildHeap(int *a,int size)    //建立堆 
{    
	int i;    
	for(i=size/2;i>=1;i--)    //非叶节点最大序号值为size/2     
	{        
		HeapAdjust(a,i,size);        
	}
} 


 

三、堆排序:

/*思想:交换堆顶和最后一个元素,即每次将剩余元素中的最大者放到最后面,

1、交换

2、重新调整三角堆

// 堆排序
// 初始调用BuildMaxHeap将a[1..size]变成最大堆
// 因为数组最大元素在a[1],则可以通过将a[1]与a[size]互换达到正确位置
// 现在新的根元素破坏了最大堆的性质,所以调用HeapAdjust调整,
// 使a[1..size-1]成为最大堆,a[1]又是a[1..size-1]中的最大元素,
// 将a[1]与a[size-1]互换达到正确位置。
// 反复调用HeapAdjust,使整个数组成从小到大排序。
// 注意: 交换只是破坏了以a[1]为根的二叉树最大堆性质,它的左右子二叉树还是具备最大堆性质。
//        这也是为何在BuildMaxHeap时需要遍历size/2到1的结点才能构成最大堆(自底往上),而这里只需要堆化a[1]即可

---swap()交换堆顶和此堆的最后一个元素
---HeapAdjust()重新调整函数-三角堆调整*/
void HeapSort(int *a,int size)    //堆排序 
{       
	BuildHeap(a,size);
	int len = size;
	for(int i=size;i>=2;i--)    
	{ 
		swap(a[1],a[i]);           //交换堆顶和最后一个元素,即每次将剩余元素中的最大者放到最后面           
		//BuildMaxHeap(a,i-1); 
		//将余下元素重新建立为大顶堆 
		len--;
		HeapAdjust(a,1,len); 
		//重新调整堆顶节点成为大顶堆  
	}
} 

3、测试代码

int main(int argc, char *argv[])
{     
	int size;
	 int a[100];
	 cout << "Input the num of elements: ";
	 cin >> size;
	 cout << "Input the elements: ";
	 for(int i=1; i<=size; ++i)
	  cin >> a[i];
	 cout << endl;
	 PrintArray(a,size);

	HeapSort(a,size);       
	PrintArray(a,size);
	return 0;
}

总结:基本操作为三角堆的(从上往下)递归调整。(i~size),i为当前三角堆的顶节点。

建堆:从下往上逐步调整三角堆。(size/2,size)。

堆排序:顶部与最末值的交换+三角堆排序

 时间复杂度:

在用数组的实现方式中,每次都把新加入的数值放入数组的末尾。如果这个数比它现在所在位置的父节点的数值小,那么就要把他俩交换。如果在新的位置上还是比它的父节点小,就递归地继续这个过程。这个过程和二叉树的高度成正比,所以是logn。如果把所有n个数都插入进来,那么最坏情况的时间就是O(n*logn).

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值