排序算法之堆排序

来源:互联网 发布:张西可形意拳网络教学 编辑:程序博客网 时间:2024/05/14 21:10

堆排序算法是选择排序的一种,该算法只是通过堆,最大堆、或者最小堆选择出一个待排序序列中的最大值,或者最小值。要想实现堆排序算法,就需要构建什么堆,这里也最小堆为例。说明什么是堆,怎么构建一个堆。

假设待排序序列为A[n] 为一个数组。数组的长度为n 数组下标为 0,1,2,…i,….2i,2i+1….n-1;

堆是一个有序的二叉树。一个二叉树满足如下条件就是一个堆。下面以最小堆为例:

l 树中的非叶节点的数据小于或者等于左右孩子节点的数据。

在队中,没有规定节点的左右孩子的大小,只规定了父节点和子节点数据之间必须满足的条件。当从小到大的顺序输出数据时,要求根节点是最大值。

下面以按照从小到大的顺序排序为例,介绍堆排序的相关内容。

堆排序有连个阶段:

1.         将无序的数据A[n]构成堆,(即用无序的数据生成满足堆定义的完全二叉树)。

2.         利用堆排序(利用上一步生成的堆输出有序的数据)。

      下面说明如何构成堆:

      获取最后一个非叶节点,和左右孩子节点比较将最大值移动到父节点。比如:n/2 就是最后一个非叶节点。假如此时一个非叶节点的序号为 k 则 k >0 并且 k< n

上一个非叶节点 k -1 , 和 2(k-1) 左节点 、2k右节点中较大的进行比较,如果大于跟节点就和跟节点进行交换,否则不交换。如果交换,加入k -1 和 2(k)交换的,则需要将2k作为父节点进行比较检测,因为k-1 和 2k进行了交换说明k-1小于 2k 而 2k 处的值是以2k为父节点的子树的最大值,一旦交换,则不能保证还是最大值。

      如A[n] = {69,65,90,37,92,6,28,54} 将其放在二叉树中,如下图所示:

   图中,黄色背景表示:进行比较的根节点。将该节点和左右子树比较,是否交换要看交换结果。第一次交换结果、第二次交换如下图:

   

本次交换,90 比6,28都大,本次比较不需要交换。

下一次比较和交换:如下图:

下一次:

   

   本次交换完成,但是因为将较小的数放在了节点2 处,一次要遍历 以 2 为根节点的所有子树,以保证,2 节点也是一个符合 左右孩子节点的值都比父节点的值小。 因此将 2 号所在未知的节点重新遍历。如下:

最后结果:

这个整个二叉树就成为一个最大堆。

以上描述的是堆的形成过程。堆排序就是基于这样的过程的。

待排序序列构成一个最大堆,然后将最大的数放在待排序序列的最后,将出去最后序列的剩余数据生成最大堆,一次循环,就可以将待排序的数据变成有序序列。

有以上可知,堆排序的过程中生成最大堆是堆排序的难点。在生成最大堆以后,很容易进行堆排序了,以下是堆排序中生成堆的流程图:

将如当前排序的序列是A[n], 最大非叶节点是 s 序列的长度为n

对排序的整体实现:C++

#include<iostream>

using namespace std;

void GengrateHeap(int array[],int s,int n);

void HeapSort(int array[],int n);

void OutPut(int array[],int n);

int main()

{

         int A[8] = {10,9,4,11,3,13,6,5};

         OutPut(A,8);

         HeapSort(A,8);

         OutPut(A,8);

         system("pause");

         return 0;

}

//输出整个排序序列

void OutPut(int array[],int n)

{

         for(int i =0;i<n;i++)

         {

                   cout<<array[i]<<" , ";

         }

         cout<<endl;

}

//将s为根节点生成一个堆

void GengrateHeap(int array[],int s,int n)

{

         int j =0;

         int temp = 0;

while(2*s+1<n)

{

         j = 2*s+1;

         if((j+1)<n)

         {

                  if(array[j]<array[j+1])

                   {

                            j++;

                   }

         }

         if(array[s]<array[j])

         {

                   temp = array[s];

                   array[s]=array[j];

                   array[j]=temp;

                   s=j;

         }

         else

         {

                   break;

         }

}

}

//堆排序的实现

void HeapSort(int array[],int n)

{       

         int temp=0;

         for(int i =n/2-1;i>=0;i--)

         {

                   GengrateHeap(array,i,n);

         }

         for(int j =n-1;j>0;j--)

         {

                   temp = array[0];

                   array[0]=array[j];

                   array[j]=temp;

                   GengrateHeap(array,0,j);

         }

}

本程序在VC++6.0中能够正确运行。

0 0
原创粉丝点击