堆排序

来源:互联网 发布:java后端游戏引擎 编辑:程序博客网 时间:2024/06/05 18:43

堆(heap)本质就是一个完全二叉树。

完全二叉树定义:若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树

而堆根据其节点所满足的性质分为:大顶(根)堆、小顶(根)堆。
所需要满足的性质为:
1.父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。
2.每个结点的左子树和右子树都是一个二叉堆(都是大顶(根)堆或小顶(根)堆)。

算法原理

在堆排序中,数据存储在一维数组中,编号范围为1~N(方便构成树)。此时数据构成了完全二叉树,但是还没有构成我们所需要的堆,这需要我们对其进行调整,这时候堆排序的核心。
这里以建立大顶堆为例,大顶堆对应着升序排序。
Code:

//i 为指定节点编号//s 为数据存储地址//last 为堆的最后一位元素编号void heap_sort(int i,int * s,int last){    int L = 2*i, R = 2*i+1;//节点的左右孩子编号    if (L>last&&R>last) return ;    int Max_LR = -1;    if (R<=last&&L>last) Max_LR = R;    if (L<=last&&R>last) Max_LR = L;    if (R<=last&&L<=last) Max_LR = (s[L]<s[R])?R:L;    if (s[Max_LR]>s[i])        {            swap_m(s[Max_LR],s[i]);            heap_sort(Max_LR, s, last);//递归调用heap_sort,保持堆数据结构        }}

经过对完全二叉树进行调整后,我们得到了一个大顶堆,但数据仍然不是我们所需要的满足升序排序的数据。
我们将堆顶元素与堆的最后一个元素进行交换,则此时堆中最大元素排在了堆的最后一位,即该元素已到达正确位置。此时,由于刚刚的交换操作,大顶堆数据结构被破坏,称为半堆。我们需要进行调整,使其恢复结构。
Code:

for (int i = N;i>=1;i--)        {            swap_m(s[i], s[1]);            heap_sort(1, s, i-1);        }

不断进行上述操作,直到堆退化到为单节点树,此时数据已满足升序排序。

原创粉丝点击