zoukankan      html  css  js  c++  java
  • 排序和顺序统计学(1)——堆排序

      也有好几天没记录算法学习情况了,这两天看了《算法导论》的第二部分,排序和顺序统计学,记录一下,也顺便增强记忆

    1.堆排序

      就是最大堆和最小堆,用一维数组存储,数据结构是完全二叉树。主要过程分为构建最大/最小堆,插入操作,弹出最大值,取最大/最小值,改变堆中的权值。

      构建堆就是从第一个非叶子节点开始,倒数到第一个节点,对于每个节点执行以下函数(最大堆为例):

    void heapify(int x)
    {
    int largest;
    if (x*2<=heapsize&&a[x] > a[x * 2]) largest = x;
    else largest = x * 2;
    if (x*2+1<=heapsize&&a[x * 2 + 1]>a[largest]) largest = x*2+1;
    if(x!=largest)
    {
    swap(a[largest],a[x]);
    heapify(largest);
    }
    }

      对于每一个节点i,将它与它的两个子节点i*2和i*2+1进行比较,将最大元素放在三者中的父亲节点,并对之前存放最大元素的节点递归式用该函数,即可构建最大堆。时间复杂度为O(nlgn),对于每个元素,递归式用该函数的最大深度为lgn,每次递归时间复杂度为常数级,共对n/2个节点执行该函数,因此时间复杂度应为n/2*a*lgn,1/2及a都是常数,略去即得O(nlgn)

      取最值:将堆顶元素取出即可,时间复杂度为O(1)

      改变值操作:书中所说为increase函数,即对于最大堆来说,只有当值增大的时候才对其改变并进行操作,否则不进行操作。操作如下:将当前元素与他的父亲节点进行比较,若比父亲节点大则互换:

    void increase(int pos,int x)
    {
    if(a[pos]<x)
    {
    a[pos] = x;
    while(pos>1&&a[pos]>a[pos/2])
    {
    swap(a[pos],a[pos/2]);
    pos = pos/2;
    }
    }
    }//将x替换pos位置的元素

    其实对于最大堆,当x<a[pos]时也是可以的,只要将调用increase函数改为调用heapify函数即可。(个人理解)

      添加值:数组长度++,并将数组末尾元素设为负无穷,对该元素调用函数increase(length[a],x),length[a]为数组a的长度,x为要插入数的大小。

      弹出最大值:即取最大值+删除堆顶元素。将堆顶元素与数组末尾元素互换,并对堆顶元素进行heapify操作即可

      输出堆排序结果:循环length[a]次弹出最值。

    以上为堆排序的各种操作。

  • 相关阅读:
    Android自定义Dialog效果
    Attempt to invoke virtual method 'void android.app.ActionBar.setTitle的解决方法
    Android 震动 和 停止 代码
    任意手机虚拟按键增加方法
    [vijos]1066弱弱的战壕<线段树>
    [bzoj]1059矩阵游戏<二分图匹配*匈牙利算法>
    [bzoj]1053反质数<暴搜>
    [codevs]1250斐波那契数列<矩阵乘法&快速幂>
    [codevs2597]团伙<并查集>
    [noip模拟赛]虫洞holes<SPFA>
  • 原文地址:https://www.cnblogs.com/kangyun/p/4356244.html
Copyright © 2011-2022 走看看