1、堆数据结构
堆数据结构:是一种数组对象。它可以视为一个完全二叉树,数中的每个节点和数组的每个元素一一对应。
最大根堆:堆中最大值存放在根节点中。并且以某一节点为根的子树中,各节点的值都不大于该子树根结点的值。
2、维护堆的性质
我们假设某一节点A[i],以A[i]的左孩子A[LEFT[i]]和右孩子A[RIGHT[i]]为根的两棵子树都是最大根堆,但这时A[i]可能小于其子女,这样就违反了最大根堆的性质。所以,我们需要做出相应的调整,使其满足最大根堆的性质。
在A[LEFT[i]]和A[RIGHT[i]]中找出最大的,然后将其下标保存在largest中,如果A[i]是最大的,则以i为根的子树是最大根堆,程序结束。否则,交换A[i]和A[largest],从而使其子女满足最大根堆性质。但是下标为largest的节点交换后值是A[i],以该节点为根的子树又有可能破坏最大根堆的性质,因此我们还需要对以largest为节点的子树递归调用维护堆性质的函数。
维护堆性质的函数:
//更新堆,保持堆的性质
//输入数组a,需调整的子树根节点i,数组长度len
void MaxHeapIfy(int *a,int i,int len)
{
int largest=i,temp;
if(2*i<=len&&a[2*i]>a[i])
{
largest=2*i;
}
if(2*i+1<=len&&a[2*i+1]>a[largest])
{
largest=2*i+1;
}
if(largest!=i)
{
temp=a[i];
a[i]=a[largest];
a[largest]=temp;
MaxHeapIfy(a,largest,len);
}
}
3、创建最大根堆
我们看可以自底向上的调用MaxHeapIfy函数来将一个数组(数组A从1到n存放元素,A[0]不存放有效元素,便于后面操作)变成一个最大根堆。我们知道子数组A[[n/2]+1,...,n]中的元素都是子树的叶子,因此可以单独看成只含一个元素的堆。所以只需要对其与元素调用MaxHeapIfy函数以创建最大根堆。
创建最大根堆函数如下:
//创建最大根堆
//输入数组a,数组最后一个元素位置n
void BuildMaxHeap(int *a,int n)
{
for (int i=n/2;i>0;i--)
{
MaxHeapIfy(a,i,n);
}
}
4、堆排序
首先将数组变成一个最大根堆,然后将根元素和数组最后一个元素互换,这样数组最后一个元素存放的是数组最大值。然后从堆中"去掉"节点n,将剩余的节点变成最大堆,继续前面一样的操作,直至最大根堆中只剩下一个根节点,此时数组排序完毕。
//堆排序
//输入数组a,数组最后一个元素位置n
void HeapSort(int *a,int n)
{
BuildMaxHeap(a,n);
for (int i=n;i>0;)
{
int temp=a[1];
a[1]=a[i];
a[i]=temp;
MaxHeapIfy(a,1,--i);
}
}
5、堆排序完整程序如下:
#include "stdafx.h"
#include "iostream.h"
#include "string.h"
#include <time.h>
#include <stdlib.h>
//更新堆,保持堆的性质
//输入数组a,需调整的子树根节点i,数组长度len
void MaxHeapIfy(int *a,int i,int len)
{
int largest=i,temp;
if(2*i<=len&&a[2*i]>a[i])
{
largest=2*i;
}
if(2*i+1<=len&&a[2*i+1]>a[largest])
{
largest=2*i+1;
}
if(largest!=i)
{
temp=a[i];
a[i]=a[largest];
a[largest]=temp;
MaxHeapIfy(a,largest,len);
}
}
//创建最大根堆
//输入数组a,数组最后一个元素位置n
void BuildMaxHeap(int *a,int n)
{
for (int i=n/2;i>0;i--)
{
MaxHeapIfy(a,i,n);
}
}
//堆排序
//输入数组a,数组最后一个元素位置n
void HeapSort(int *a,int n)
{
BuildMaxHeap(a,n);
for (int i=n;i>0;)
{
int temp=a[1];
a[1]=a[i];
a[i]=temp;
MaxHeapIfy(a,1,--i);
}
}
int main(int argc, char* argv[])
{
int a[]={0,23,5,35,32,435,42,75,24,24,12,64,53,31,97,75,324,75,86,9,54,24,235};
int len=sizeof(a)/sizeof(int);
HeapSort(a,len-1);
for (int i=0;i<len;i++)
{
cout<<a[i]<<" ";
}
cout<<endl;
return 0;
}