zoukankan      html  css  js  c++  java
  • 倍道而行 :堆(heap)

    概念


     先来两个概念(别头疼):

    普通队列:先进先出,后进后出

    优先队列出队顺序和入队顺序无关;和优先级相关。就好比:我们的电脑操作系统会按照各个进程的优先级来安排CPU执行哪一个进程。

    堆(heap)被称为一种优先队列,但是堆的本质不是队列。取出顺序就是每次取最大的呗。

    下图就是一个堆:

    本质就是一个完全二叉树。完全二叉树的定义看图就可得出:父节点都大于等于子节点。且是从上大下,从左至右的排序。

    堆的实现


    看图:

    仔细看每个数的下标。数组是从1开始的。父节点和子节点的关系也可以很容易得出。

    eg:41是28和16的父节点,下标分别为2、4、5,满足图中的公式。

    如题:有10个数,请用代码将之组成一个堆?

    算法思想:每次往里面插入一个数,我们只需要比较插入的数和其父节点数的大小就行。

    代码:

    k指的是插入的序号。建议大家这样理解:
    假设现在已经构建好了有10个数的堆,我再往里面插入一个数为102,即第11个数。那么k=11.然后与其父节点(k/2=5),即arr[5]进行比较。若大于父节点就交换位置,并让k/2=2,继续进行下去,至到和根结点进行比较。
    void
    shiftUp(int k,int arr[]){ while (k>1 && arr[k/2]<arr[k]) { swap(arr[k/2], arr[k]); k /=2; } }

     取堆里面的数:每次取都是取第一个位置的数,也就是最大的数。


     如题:现在构建好了一个堆,那么我取走第一个数后,整个堆就需要进行调整,那该如何?

    目前思想:(以本遍博客上面的例子为例,读者可以对照着看) 

    本题的:k代表开始的位置为1,j为子节点的位置(eg:指的是62这个根的左右两个子节点)

    • 1.取走62,我就让15代替62的位置。即,用最末尾的数字放到根节点上。
    • 2.比较用15和62的两个左右节点进行比较,如果大就不做处理,否则交换位置并且,让k=j.
    • 继续走第二步
    void shiftDown(int k,int arr[],int count ){
        while (2*k< count) { //确认有左子节点
            int j = 2*k;
            if (j+1<count && arr[j+1] > arr[j]) { //如果有右节点
                j+=1; 
            }
            if (arr[k]>arr[j]) { 如果,比较发现字节点没有父节点大,就退出
                break;
            }
            swap(arr[k], arr[j]);//否则就交换位置
            k = j;//然后让k=j,继续进行比较。
        }
    }

    结尾:     


     堆排序算法还是很简单的。

    建立堆,然后一个一个的取出,那么这就是一个从大到小的一个有序的序列。

    但行好事,莫问前程。
  • 相关阅读:
    jquery.stop()停止动画
    字符串转义
    CSS规范 (命名)- 分类方法
    inline-block 间距
    jquery中offset(),position()
    PHP把数组转换为JSON字符串
    json对象
    C#-静态实例
    C#-readonly与const区别
    SQL-事务隔离级别与锁
  • 原文地址:https://www.cnblogs.com/yuhui-snail/p/8581107.html
Copyright © 2011-2022 走看看