• 堆排序


    这里以小顶堆为例:

    思路:

    对于堆排序来说,首先需要做的是要建堆,建堆是一个不断调整堆的过程,能够在线性时间内完成。

    堆排序的过程
    1、建堆,建堆是不断调整堆的过程,从len/2处开始调整,一直到第一个节点,此处len是堆中元素的个数。建堆的过程是线性的过程,从len/2到0处一直调用调整堆的过程,相当于o(h1)+o(h2)…+o(hlen/2) 其中h表示节点的深度,len/2表示节点的个数,这是一个求和的过程,结果是线性的O(n)。
    2、调整堆:调整堆在构建堆的过程中会用到,而且在堆排序过程中也会用到。利用的思想是比较节点i和它的孩子节点left(i),right(i),选出三者最大(或者最小)者,如果最大(小)值不是节点i而是它的一个孩子节点,那边交互节点i和该节点,然后再调用调整堆过程,这是一个递归的过程。调整堆的过程时间复杂度与堆的深度有关系,是lgn的操作,因为是沿着深度方向进行调整的。
    3、堆排序:堆排序是利用上面的两个过程来进行的。首先是根据元素构建堆。然后将堆的根节点取出(一般是被最后一个节点覆盖掉),将前面len-1个节点继续进行堆调整的过程,然后再将根节点取出,这样一直到所有节点都取出。堆排序过程的时间复杂度是O(nlgn)。因为建堆的时间复杂度是O(n)(调用一次);调整堆的时间复杂度是lgn,调用了n-1次,所以堆排序的时间复杂度是O(nlgn)

    代码:

     1 #include <fstream>
     2 #include <iostream>
     3 #include <algorithm>
     4 #include <cstdio>
     5 #include <cstring>
     6 #include <cmath>
     7 #include <vector>
     8 #include <cstdlib>
     9 
    10 using namespace std;
    11 
    12 #define PI acos(-1.0)
    13 #define EPS 1e-10
    14 #define lll __int64
    15 #define ll long long
    16 #define INF 0x7fffffff
    17 
    18 //tree为小根堆(这里用数组来实现)
    19 vector<int> tree;
    20 //排好序的序列fix
    21 int *fix;
    22 
    23 void buildTree();
    24 void insertElement(int x);
    25 void deleteMinElement();
    26 void swim(int ii);
    27 void order();
    28 
    29 int main(){
    30     //freopen("D:\input.in","r",stdin);
    31     //freopen("D:\output.out","w",stdout);
    32     int n;
    33     scanf("%d",&n);
    34     tree.resize(n+1);
    35     for(int i=1;i<=n;i++)    scanf("%d",&tree[i]);
    36     buildTree();
    37     insertElement(9);
    38     deleteMinElement();
    39     n=tree.size();
    40     fix=new int[n];
    41     order();
    42     for(int i=1;i<n;i++)    printf("%d ",fix[i]);
    43     return 0;
    44 }
    45 void buildTree(){
    46     int cur=(tree.size()-1)/2;
    47     while(cur){
    48         swim(cur);
    49         cur--;
    50     }
    51 }
    52 void insertElement(int x){
    53     tree.push_back(x);
    54     int cur=tree.size()-1;
    55     int son;
    56     while(1){
    57         son=cur;
    58         cur>>=1;
    59         if(!cur){
    60             tree[son]=x;
    61             break;
    62         }
    63         if(tree[cur]>=x){
    64             tree[son]=tree[cur];
    65         }else{
    66             tree[son]=x;
    67             break;
    68         }
    69     }
    70 }
    71 void deleteMinElement(){
    72     tree[1]=tree[tree.size()-1];
    73     tree.pop_back();
    74     swim(1);
    75 }
    76 void swim(int ii){
    77     int son,t=tree[ii];
    78     int n=tree.size()-1;
    79     while((ii<<1)<=n){
    80         if((ii<<1)+1<=n&&tree[ii<<1]>=tree[(ii<<1)+1])   son=(ii<<1)+1;
    81         else    son=(ii<<1);
    82         if(t>tree[son]){
    83             tree[ii]=tree[son];
    84             ii=son;
    85         }else{
    86             break;
    87         }
    88     }
    89     tree[ii]=t;
    90 }
    91 void order(){
    92     int cur=1;
    93     while(tree.size()!=1){
    94         fix[cur++]=tree[1];
    95         deleteMinElement();
    96     }
    97 }
  • 相关阅读:
    46)父类和子类出现重名变量
    45)子类的构造和析构
    44)子类与父类之间的兼容性问题
    43)继承的方式
    42)子类继承 有参父类 和无参父类
    41)子类和父类的内存关系
    40)类与类之间的关系(has use is)
    jquery学习之1.15-克隆节点
    jquery学习之1.14-删除节点
    jquery学习之1.13-节点插入-外部插入和内部插入
  • 原文地址:https://www.cnblogs.com/jiu0821/p/4415851.html
Copyright © 2020-2023  润新知