经典排序算法 - 堆排序Heap sort
堆排序有点小复杂,分成三块
第一块,什么是堆,什么是最大堆
第二块,怎么将堆调整为最大堆,这部分是重点
第三块,堆排序介绍
第一块,什么是堆,什么是最大堆
什么是堆
这里的堆(二叉堆),指得不是堆栈的那个堆,而是一种数据结构。
堆可以视为一棵完全的二叉树,完全二叉树的一个“优秀”的性质是,除了最底层之外,每一层都是满的,这使得堆可以利用数组来表示,每一个结点对应数组中的一个元素.
数组与堆之间的关系
二叉堆一般分为两种:最大堆和最小堆。
什么是最大堆
堆中每个父节点的元素值都大于等于其孩子结点(如果存在),这样的堆就是一个最大堆
因此,最大堆中的最大元素值出现在根结点(堆顶)
节点与数组索引关系
对于给定的某个结点的下标i,可以很容易的计算出这个结点的父结点、孩子结点的下标,而且计算公式很漂亮很简约
第二块,怎么将堆调整为最大堆,这部分是重点
整个过程如下图所示
在4,14,7这个小堆里边,父节点4小于左孩子14,所以两者交换
在4,2,8这个小堆里边,父节点4小于右孩子8,所以两者交换
上图展示了一趟调整的过程,这个过程递归实现,直到调整为最大堆为止
第三块,堆排序介绍
堆排序就是把堆顶的最大数取出,
将剩余的堆继续调整为最大堆,具体过程在第二块有介绍,以递归实现
剩余部分调整为最大堆后,再次将堆顶的最大数取出,再将剩余部分调整为最大堆,这个过程持续到剩余数只有一个时结束
下边三张图详细描述了整个过程
以上部分为转载他人文献,转载地址:http://www.cnblogs.com/kkun/archive/2011/11/23/2260286.html
我在学习过程中,从文章看到的不太全面,自己写的时候也用了不少的时间来琢磨,才基本弄懂。
这里把我写的程序附上,加上了解释,希望能帮助到初学此算法的朋友。
#include <iostream>
using namespace std;
int array1[10]={4,2,1,0,6,7,9,3,8,5};
void AdjustHeapToMax(int *a,int maxNumber,int size);//调整堆为最大堆
void swapEx(int &a,int &b);//交换值
void DisplayHeap(int *head,int number);//显示堆
void HeapSort(int *a,int size);//堆排序 a为需要排序的数组 size为数组的大小
int main()
{
cout<<"排序前"<<endl;
DisplayHeap(array1,10);
HeapSort(array1,10);
cout<<"排序后"<<endl;
DisplayHeap(array1,10);
system("pause");
return 0;
}
//a为需要排序的数组
//parentNumber为父节点的值
//size为排序数组的大小
void AdjustHeapToMax(int *a,int parentNumber,int size)
{
int lChild=2*parentNumber+1;//左子节点
int rClild=2*parentNumber+2;//右子节点
int max;//当前二叉树中值最大的节点的下标
max=parentNumber;//初始值认为父节点对应的值为最大
if (lChild<size&&a[lChild]>a[max])//与左子节点比较,取值大的下标
{
max=lChild;
}
if (a[rClild]>a[max]&&rClild<size)//与右子节点比较,取值大的下标
{
max=rClild;
}
if (max!=parentNumber)//如果在比较中,父节点不是最大的,则与最大值交换,并且继续调用函数,直到父节点是最大值为止
{
swapEx(a[max],a[parentNumber]);
AdjustHeapToMax(a,parentNumber,size);
}
}
void swapEx(int &a,int &b)
{
int temp;
temp=a;
a=b;
b=temp;
}
void HeapSort(int *a,int size)//a为需要排序的数组 size为数组的大小
{
for (int j=size;j>=1;j--)//此循环每循环一次,则最后一位成为最大值,下次循环不再加入排序
{
//比较时是分为一个一个小的二叉树来比较,由下往上,由右往左,比较后把最大的值放到父节点中,
//比较到最后,则根节点为最大值,然后交换根节点与最后一个节点的值。
for (int i=(j/2-1);i>=0;i--)
{
AdjustHeapToMax(array1,i,j);
}
swapEx(a[0],a[j-1]);
}
}
void DisplayHeap(int *head,int number)//为了测试时好看。。。
{
cout<<" "<<head[0]<<endl;
cout<<" "<<head[1]<<" "<<head[2]<<endl;
cout<<" "<<head[3]<<" "<<head[4]<<" "<<head[5]<<" "<<head[6]<<endl;
cout<<head[7]<<" "<<head[8]<<" "<<head[9]<<endl;
cout<<endl;
}
代码执行结果如下: