zoukankan      html  css  js  c++  java
  • 大根堆,小根堆,堆排序 木

    大根堆: 根节点value不小于子节点的value,满足这条性质的二叉树即为大根堆。

    小根堆:根节点value不大于子节点的value,满足这条性质的二叉树即为小根堆。

    从大根堆的定义可知:在大根堆里要得到最大值只需o(1)的时间。所以很明显,大根堆可以求最大值和维护前k小的数。注意是前k小的数,不是前k大的数,因为当前要插入到堆里的数可以直接和堆里最大值考虑,如果比堆里最大的都还要小,那就那这个值放到堆里,这样就维护了前k小的数。

    如果k很大的话,要划分为很多个堆。小根堆和大根堆相反。

    堆的操作主要有:

    bool isEmpty(int *a); // 判断堆是否为空
    bool isFull(int *a); //判断堆是否为满
    int top(int *a);// 返回堆顶元素
    void pop(int *a);//删除堆顶元素

    pop是删除堆顶元素,直接把最后面那个元素的值赋给堆顶,同时元素个数减一,然后是调整堆。

    void push(int *a,int);//插入元素

    push之前要判断空间是否为满,直接把value放到堆最后,然后是调整堆。

    代码:

    View Code
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 using namespace std;
      6 
      7 #define maxSize 200008<<2
      8 int heap[maxSize];
      9 
     10 bool isEmpty(int *a);
     11 bool isFull(int *a);
     12 int top(int *a);
     13 void pop(int *a);
     14 void push(int *a, int);
     15 
     16 template <typename T>
     17 void Swap( T& a, T& b)
     18 {
     19     T tmp = a; a = b; b = tmp;
     20 }
     21 
     22 // 判空
     23 bool isEmpty(int *a){
     24     return a[0]<=0? true: false;
     25 }
     26 //
     27 bool isFull(int *a){
     28      return a[0]+1>=maxSize? true: false;
     29 }
     30 
     31 int top(int *a){
     32     if(isEmpty(a) ) {
     33          puts("since for the heap is empty, the operation is illegel!");
     34          exit(0);
     35     }
     36     return heap[1];
     37 };
     38 
     39 // 调整堆,自上往下
     40 void adjust( int *a ) {
     41      int i = 1;
     42      while(  i <= a[0] ){
     43          if((i<<1|1) <= a[0] ) // 存在左右子树。
     44          {
     45              if(a[i<<1] > a[i] && a[i<<1]>a[i<<1|1]){
     46                    Swap(a[i<<1], a[i]); i <<= 1;
     47              }else if(a[i<<1|1] > a[i]) {
     48                   Swap(a[i<<1|1], a[i]);
     49                   i = i<<1|1;
     50              }else break;
     51 
     52          }else if( (i<<1) <= a[0] ) { // 只存在左子树
     53              if(a[i<<1] > a[i]){
     54                  Swap(a[i<<1], a[i]); i <<= 1;
     55              }else break;
     56 
     57          }else break;
     58      }
     59 }
     60 
     61 void pop(int *a){
     62     if(isEmpty(a) ) {
     63          fprintf(stderr, "the heap is empty!");
     64          exit(0);
     65     }
     66     a[1] = a[a[0]-- ];
     67     adjust(a);
     68 }
     69 
     70 void outPut(int *a){
     71      puts("***********************************\n");
     72      if(isEmpty(a) ) puts("the heap is empty!");
     73      else
     74      {
     75          for ( int i=1; i<=a[0]; ++i)
     76             printf("%d %d\n", i, a[i]);
     77      }
     78      puts("***********************************\n");
     79 }
     80 
     81 void push(int *a, int value){
     82     if(isFull(a) ) {
     83          fprintf(stderr, "the heap is full!\n");
     84          return ;
     85     }
     86     a[++a[0] ] = value;
     87     int i = a[0]; // 调整堆,自下而上
     88     while(i > 1 && a[i] > a[i/2]) {
     89         Swap(a[i], a[i/2]); i >>= 1;
     90     }
     91 };
     92 
     93 int main()
     94 {
     95     heap[0] = 0; // 记录元素个数;
     96     printf("push five intgers: ");
     97     for ( int i=0, tmp; i<5; ++i ) {
     98         scanf ("%d", &tmp);
     99         push(heap, tmp); // 插入元素
    100     }
    101     outPut(heap); // 输出堆
    102 
    103     int maxx = top(heap); // 取出堆的最大值
    104     printf("the maxx in current tree is %d \n", maxx);
    105 
    106     // 删除堆顶(最大值)
    107     printf("delete tha top node.\n");
    108     pop(heap);
    109     outPut(heap);
    110 
    111     printf("输入一个元素进行插入操作:");
    112     int tmp; scanf("%d", &tmp);
    113     push(heap, tmp);
    114     outPut(heap);
    115 
    116     printf("clear the heap.\n");
    117     while(!isEmpty(heap) ) pop(heap);
    118     printf("the size of the heap is %d\n", heap[0]);
    119 
    120     system("pause");
    121 };

    堆排序: 向大根堆中插入和删除元素的时间都是0(logn),根据这两个操作的时间,可以知道堆排序的时间复杂度为n*log(n). 堆排序思路: 在待排序的元素中建立大根堆,每次都把最大的取出来,这样就完成了排序。未完,待续。。。。

  • 相关阅读:
    趣谈编程史第4期-饱受争议的前端之王JavaScript的血泪成长史
    趣谈编程史第2期-这个世界缺少对C语言的敬畏,你不了解的C语言科普
    趣谈编程史第1期-跌宕起伏的java帝国史,剖析谷歌甲骨文长达8年的版权战争
    记录一次Metaspace扩容引发FGC的调优总结
    多线程学习笔记-深入理解ThreadPoolExecutor
    使用CompletableFuture优化你的代码执行效率
    Linux+Shell常用命令总结
    Guava Cache探索及spring项目整合GuavaCache实例
    将List按照指定大小等分的几种实现方式和效率对比及优化
    Spring的事件机制详解
  • 原文地址:https://www.cnblogs.com/TengXunGuanFangBlog/p/data_structure.html
Copyright © 2011-2022 走看看