经典排序算法-堆排序HeapSort

来源:互联网 发布:windows xp outlook 编辑:程序博客网 时间:2024/05/18 02:32

经典排序算法 - 堆排序Heap sort

堆排序有点小复杂,分成三块

第一块,什么是堆,什么是最大堆

第二块,怎么将堆调整为最大堆,这部分是重点

第三块,堆排序介绍


第一块,什么是堆,什么是最大堆

什么是堆

这里的堆(二叉堆),指得不是堆栈的那个堆,而是一种数据结构。

堆可以视为一棵完全的二叉树,完全二叉树的一个“优秀”的性质是,除了最底层之外,每一层都是满的,这使得堆可以利用数组来表示,每一个结点对应数组中的一个元素.

数组与堆之间的关系

Heap1

二叉堆一般分为两种:最大堆和最小堆。

什么是最大堆

堆中每个父节点的元素值都大于等于其孩子结点(如果存在),这样的堆就是一个最大堆

因此,最大堆中的最大元素值出现在根结点(堆顶)

节点与数组索引关系

对于给定的某个结点的下标i,可以很容易的计算出这个结点的父结点、孩子结点的下标,而且计算公式很漂亮很简约

Image(2)

第二块,怎么将堆调整为最大堆,这部分是重点

整个过程如下图所示

在4,14,7这个小堆里边,父节点4小于左孩子14,所以两者交换

在4,2,8这个小堆里边,父节点4小于右孩子8,所以两者交换

Heap3

上图展示了一趟调整的过程,这个过程递归实现,直到调整为最大堆为止

第三块,堆排序介绍

堆排序就是把堆顶的最大数取出,

将剩余的堆继续调整为最大堆,具体过程在第二块有介绍,以递归实现

剩余部分调整为最大堆后,再次将堆顶的最大数取出,再将剩余部分调整为最大堆,这个过程持续到剩余数只有一个时结束

下边三张图详细描述了整个过程

Heap4

Heap5

Heap6

以上部分为转载他人文献,转载地址: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;


}

代码执行结果如下:


0 0