按自己的理解,可以分成很多个三角堆叠加。那么堆的调整就是对三角堆的调整:把最大值或最小值交换到三角堆的顶部,再递归。
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)。
堆排序:顶部与最末值的交换+三角堆排序
时间复杂度: