堆排序

原创 2015年07月08日 20:25:48

        堆是一种完全二叉树,分为小根堆和大根堆。大根堆中任意节点的值都不大于其父节点的值。有些类似于二叉搜索树,都是要求父节点和子节点的值满足某种关系。

        堆排序的基本思想是,先用所给数据建立大根堆,堆顶元素即为最大值,将其与最后一个元素交换,此时最后一个元素为最大值;再对最大值之前的元素进行调整,使其恢复为大根堆。再如此将次大值取出排列在最大值之前,循环往复,直到所有元素都排好序。

        于是,排序的关键就是建堆和调整。如下HeapAjust函数实现调整树的功能,使其满足堆的性质。算法是:从一个指定节点开始,如果某个节点的值小于其子节点的值,就将其与较大的子节点交换,以使当前父节点与子节点满足堆的性质;然而,进行调整后,以被交换的子节点为根的子树可能又不满足堆的性质了,因此需要继续向下迭代遍历,直到当前节点满足堆的性质,就退出循环。

        这是调整函数,想要建立堆,需要从最后一个非叶节点开始,自底向上调用此函数。堆排序时,每次取出堆中的最大元素后,要对剩下的元素进行调整,以维持堆的性质。直到所有节点都已取出,完成排序。

这是百度百科中调整函数、堆排序函数及测试代码:

#include <stdio.h>

//array是待调整的堆数组,i是待调整的数组元素的位置,nlength是数组的长度
//本函数功能是:调整以第i个节点(即值为array[i]的节点)为根节点的树,使其成为大根堆 
void HeapAdjust(int array[], int i, int nLength)
{
    int nChild;
    int nTemp;
    
    for(; 2*i+1 < nLength; i=nChild)
    {
        //子结点的位置=2*(父结点位置)+1
        nChild = 2*i+1;
        
        //得到子结点中较大的结点
         if(nChild < nLength-1 && array[nChild+1] > array[nChild])
            ++nChild;
            
        //如果较大的子结点大于父结点那么把较大的子结点往上移动,替换它的父结点
         if(array[i] < array[nChild])
        {
            nTemp=array[i];
            array[i]=array[nChild];
            array[nChild]=nTemp; 
        }
        else 
             break; //否则退出循环
    }
}   
//堆排序算法
void HeapSort(int array[], int length)
{
    int i, j;
    
    //建堆 
    //调整序列的前半部分元素,调整完之后第一个元素是序列的最大的元素
    //length/2-1是最后一个非叶节点,此处"/"为整除
    for(i=length/2-1; i>=0; --i)
    {
        HeapAdjust(array, i, length);
    }
    
    //从最后一个元素开始对序列进行调整,不断的缩小调整的范围直到第一个元素
     for(i=length-1; i>0; --i)
    {
        //把第一个元素和当前的最后一个元素交换,
         //保证当前的最后一个位置的元素都是在现在的这个序列之中最大的
         array[i] = array[0]^array[i];
        array[0] = array[0]^array[i];
        array[i] = array[0]^array[i];
        
        //不断缩小调整heap的范围,每一次调整完毕保证第一个元素是当前序列的最大值
         HeapAdjust(array,0,i);
    }
}

int main()
{
    int i;
    int num[]={0,1,2,3,4,5,6,7,8,9};
    
    HeapSort(num, sizeof(num)/sizeof(int));
    
    for(i=0; i < sizeof(num)/sizeof(int); i++)
    {
        printf("%d ",num[i]);
    }
    
    printf("\n");
        
    return 0;
}


 

堆排序之Java实现

  • 2017年07月27日 17:03
  • 4KB
  • 下载

堆排序法.cpp

  • 2015年07月26日 12:45
  • 2KB
  • 下载

第十五周项目一(6)——堆排序

*Copyright(c)2017,烟台大学计算机与控制工程学院 *All rights reservrd. ...

堆排序及其用途

  • 2016年03月25日 13:46
  • 214KB
  • 下载

堆排序算法c语言实现

  • 2015年10月25日 14:24
  • 2KB
  • 下载

5. 堆,建堆算法,堆排序

堆 堆实际上是一棵完全二叉树,其任何一非叶节点满足性质: Key[i]=Key[2i+1]&&key>=key[2i+2] 即任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字。 堆分为大...

堆排序

  • 2014年12月25日 21:57
  • 205KB
  • 下载

堆排序算法导论

  • 2013年11月11日 23:54
  • 152KB
  • 下载

C++实现堆、最大堆、最小堆 -- 堆排序插入删除操作

堆是一种经过排序的完全二叉树,其中任一非终端节点的数据值均不大于(或不小于)其左孩子和右孩子节点的值。 最大堆和最小堆是二叉堆的两种形式。 最大堆:根结点的键值是所有堆结点键值中最大者。 最小堆:根结...

堆排序算法

  • 2013年10月27日 09:53
  • 5KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:堆排序
举报原因:
原因补充:

(最多只允许输入30个字)