模板:堆

Posted 全宇宙唯一指定最菜的菜鸡的博客

tags:

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

做点好人好事攒点RP:浙大acm模板.pdf

度盘:https://pan.baidu.com/s/1slLnJHF

最近看到一个堆的模板(浙大的acm模板),贴过来

#define MAXN 10000
#define _cp(a,b) ((a)<(b))
typedef int elem_t;
struct heap{
  elem_t h[MAXN];
  int n,p,c;
  void init(){n=0;}
  void ins(elem_t e){
    for (p=++n;p>1&&_cp(e,h[p>>1]);h[p]=h[p>>1],p>>=1);
    h[p]=e;
  }
  int del(elem_t& e){
    if (!n) return 0;
    for
      (e=h[p=1],c=2;c<n&&_cp(h[c+=(c<n-1&&_cp(h[c+1],h[c]))],h[n]);h[p]=h[c],p=c,c<<=1);
    h[p]=h[n--];return 1;
  }
};

代码倒是写的很好,又快又短,而且封装性很好,水平和我看过的几个STL原型差不多了

至少比我写的又慢又长而且封装性差的一批(最重要的是我打的是错的)的堆写的好多了

然而很难懂,如果硬背的话估计会打错,要是打错了估计调试一辈子都调不出来

所以我就手动把这些代码翻译成了正常的(误)C++语言

首先来一个我自己打的堆(调试了一上午终于打对了)

#include <stdio.h>
#define MAXN 3000000
#define SWAP(a, b) ((a)^=(b),(b)^=(a),(a)^=(b))
struct heap {
  int H[MAXN], cnt;
  inline void push(int a) {
    int s, f;
    H[++cnt] = a;
    s = cnt, f = (s>>1); 
    while(s > 1 && H[s] < H[f]) {
      SWAP(H[s], H[f]);
      s = f;
      f = (s>>1); 
    }
  }
  inline int pop() {
    if(cnt < 1) return -1; 
    int ret = H[1];
    H[1] = H[cnt--];
    int s = 2, f = 1;
    while(s <= cnt) {
      if(s < cnt && H[s] > H[s+1]) s++;
      if(H[f] > H[s]) {
    SWAP(H[s], H[f]);
    f = s;
    s <<= 1; 
      }
      else break;
    }
    return ret; 
  }
};

然后来一个用正常C++翻译过来的浙大模板:

#define MAXN 10000
#define _cp(a,b) ((a)<(b))
typedef int elem_t;
struct heap{
  elem_t h[MAXN];
  int n,p,c;
  void init(){n=0;}
  void ins(elem_t e){
    for (p=++n;p>1&&_cp(e,h[p>>1]);h[p]=h[p>>1],p>>=1);
    h[p]=e;
  }
    //前面都看的懂吧就只加几个注释,不改了
    //p = ++n: p是当前儿子节点,++n是堆的末尾位置
    //p > 1:即p>>1 > 0,总不能超出堆的范围吧
    //_cp(e, h[p>>1]:因为这个实现是替换父子元素,所以如果插入的地方比插入的元素大,就把重复的地方替换掉,结束
    //h[p] = h[p>>1]:替换父子元素
    //p >>= 1: 跳上去
    //h[p] = e:插入的地方比插入的元素大,那么就替换掉重复的子节点,结束。
    //具体还不清楚的画一条链模拟一下就清楚了
    //实在不懂就看看这个硬式翻译的ins2吧
  void ins2(elem_t e) {
    p = ++n; 
    while(p > 1 && e < h[p>>1]) {
      h[p] = h[p>>1]; 
      p >>= 1; 
    }
    h[p] = e; 
  }

  int del(elem_t& e){
    if (!n) return 0;
    for
      (e=h[p=1],c=2;c<n&&_cp(h[c+=(c<n-1&&_cp(h[c+1],h[c]))],h[n]);h[p]=h[c],p=c,c<<=1);
    h[p]=h[n--];return 1;
  }
  int del2(elem_t& e) {
    if(!n) return 0; 
    p = 1; 
    c = 2; 
    e = h[p]; 
    while(c <= n-1) {
      if(c < n-1 && h[c+1] < h[c]) c++; 
      if(h[c] >= h[n]) break; 
      h[p] = h[c]; 
      p = c; 
      c <<= 1; 
    }
    h[p] = h[n--]; 
    return 1; 
  }
  //我真不知道这个人类是如何把这么多代码缩到一个for里面去的,zyys
}; 

 

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

VSCode自定义代码片段2——.vue文件的模板

VSCode自定义代码片段(vue主模板)

Eclipse 中的通用代码片段或模板

调用模板化成员函数:帮助我理解另一个 *** 帖子中的代码片段

vscode代码片段生成vue模板

xml Eclipse模板(代码片段)检查参数并最终抛出IllegalArgumentException