算法导论—排序算法学习(3)

来源:互联网 发布:win10软件限制策略 编辑:程序博客网 时间:2024/06/05 00:46

三.堆排序

  堆排序与归并排序一样,他们的时间复杂度都是o(log n),但是堆排序优于归并排序且与插入排序相同的是,任何时候都只需要申请常数个临时空间来存储数据。因此,堆排序是集合了归并排序与插入排序优点的一种排序方法。
  
  涉及到堆排序,首先要了解堆这种数据结构。堆是一个数组,它可以被看成一个近似的完全二叉树,树上的每一个节点对应数组中的一个元素。除了最底层外,该树是完全充满的,而且是从左向右填充。需要注意的是,当根节点是从1开始计算个数时,我们很容易计算的到它的父节点,左孩子和右孩子的下标。假设父节点下标是i,左孩子下标应该是2i,右孩子下标应该是2i+1。如果根节点是从0开始计算个数时,左孩子下标应该是2i+1,右孩子是2i+2。
  
  堆可以分为两种形式:最大堆和最小堆。最大堆性质是指除了根以外的所有节点 i 都要满足A[parent[i]]>=A[i];而最小堆性质是指除了根以外的所有节点 i 都要满足A[parent[i]]<=A[i];在堆排序中,我们使用最大堆。

  下面介绍堆排序需要的过程以及代码:
  MaxHeapify是用于维护最大堆性质的重要过程,它的输入为一个数组A和下标 i 。在调用此函数时,我们假定根节点为Left(i)和Right(i)的二叉树都是最大堆,但这时A[i]有可能小于其孩子,这样就违反了最大堆的性质。MaxHeapify通过让A[i]的值在最大堆中逐级下降,从而使得下标 i 为根节点的子树重新遵循最大堆的性质。

void MaxHeapify(int *Array,int num,int i)   //num为数组长度,i为待最大堆化的下标 {                                                        int left,right,mid,media;    left = 2*i+1;           //将该下标对应的左孩子下标赋给left     right = 2*(i+1);        //将该下标对应的右孩子下标赋给right     if(left<=(num-1) && Array[i]<Array[left])           //当左右孩子不为空时,找出父节点与左右孩子之间的最大值         mid = left;                                     else mid = i;                                       if(right<=(num-1) && Array[mid]<Array[right])            mid = right;                                    if(i != mid)            //若父节点不为最大值,则进行交换     {        media = Array[i];        Array[i] = Array[mid];        Array[mid] = media;        MaxHeapify(Array,num,mid);                      //将交换过后的值进行递归操作,继续进行最大堆化     }                        }

  有了最大堆化的操作过程,将任意一个数组变成一个最大堆的操作就成为可行的了,由二叉树的性质可知,子数组A[0,1,2…(num/2)-1]都不是叶节点,即只需要对这些元素遍历最大堆化即可:

void BuildMaxHeap(int *Array,int num){    int i;    for(i=(num/2)-1;i>=0;i--)        MaxHeapify(Array,num,i);}

  下面是堆排序的过程:

void HeapSort(int *Array,int num){    int i,media;     BuildMaxHeap(Array,num);    //首先将一个无序数组建成一个最大堆     for(i=num-1;i>=1;i--)       //此时,数组首元素必为最大元素     {                           //将数组末尾元素与首元素进行交换         media = Array[i];       //交换后则当前数组最大元素位置正确         Array[i] = Array[0];        Array[0] = media;        num -= 1;             //排序好一个元素后将最大堆减少一个节点         MaxHeapify(Array,num,0);                            //因为末尾元素此时在根节点需要重新进行最大堆化     }}
0 0
原创粉丝点击