堆排序

Posted happyknockoncode

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了堆排序相关的知识,希望对你有一定的参考价值。

堆排序

  1. 大根堆,小根堆:所有非叶子节点大于或者小于其孩子节点。

  2. 用大根堆进行从小到大的排序

  3. 建立大根堆:从下往上,从右往左遍历非叶子节点,判断其是否符合大根堆性质,若不符合,则交换节点位置,直至建出大根堆。

  4. 大根堆根节点一定是被排序的这段数值的最大值,交换堆尾堆首数值,堆尾指针前移(有没有冒泡的感觉?最大值逐渐飘到堆尾)

  5. 当前堆只有根节点不符合大根堆性质,所以从根节点开始,向下找到合适的位置即可

 1#include<stdio.h>
2#include<iostream>
3using namespace std;
4
5/**刚还奇怪,为什么从小到大排序用的是大根堆?
6仔细看,建好堆以后,根节点是最大值,可是!!!
7交换了堆尾和堆首的值,那么最大值就跑到了后面.
8交换后,这个堆尾就算最大值了 ,不用管,再排序前面 n-1 个节点
9同理,每次最大值都跑到了后面
10*/

11
12
13/**以 k 为根的完全二叉树,分别以2*K 和 2*k+1 为根的左右子树为大根堆*/
14/**使 k 为根的树满足堆的性质*/
15void sift(int a[],int k,int m)
16
{
17    int x=a[k];
18    int i=k;
19    int j=k*2;
20    bool finish=false;
21    while(j<=m&&!finish)
22    {
23        if(j+1<=m&&a[j]<a[j+1])
24            j=j+1;/**此时 j 指向最大子树根节点*/
25
26        if(x>=a[j])
27            finish=true;
28        else/**若是比子树根小,交换后还得考虑下层大小关系*/
29        {
30            a[i]=a[j];
31            i=j;
32            j=2*i;
33        }
34    }
35    a[i]=x;
36}
37void crateHeap(int a[],int n)
38
{
39    /**从最后一个非叶子节点往上筛选建堆*/
40    for(int i=n/2;i>=1;i--)
41        sift(a,i,n);
42}
43void heapSort(int a[],int n)
44
{
45    /**建大根堆后 ,保证了下面的数字不会大于上面的数字*/
46    crateHeap(a,n);
47    /**对 a 数组进行 从小到大 堆排序*/
48    for(int i=n;i>=2;i--)
49    {
50        /**每次得到的最大值跑到了后面*/
51        swap(a[i],a[1]);
52
53
54        /**交换以后只有堆顶元素是不合法的,所以下面只是为了
55        给堆顶元素找到一个合适的位置*/

56        /**对a[1~i-1]调整成堆*/
57        sift(a,1,i-1);
58    }
59}
60int main()
61
{
62    int a[12]={0,88,32,34,12,34,66,52,33,25,20};
63    heapSort(a,10);
64    for(int i=1;i<=10;i++)
65        printf("%d ",a[i]);
66    return 0;
67}

以上是关于堆排序的主要内容,如果未能解决你的问题,请参考以下文章

选择排序(简单选择排序堆排序的算法思想及代码实现)

排序--08---堆排序

python代码实现堆排序

算法-java代码实现堆排序

一文带你了解堆排序

堆排序