zoukankan      html  css  js  c++  java
  • AVL树入门

    AVL树,平衡树的一种,插入,删除,询问均为O(lgn)。

    这些天学了下它的实现,(删除貌似很麻烦,还不会。。)

    它的插入同查找树,之后靠旋转来维持平衡。

    旋转分4种情形:LL, LR, RL, RR;

    LL 可以 由一次右单旋平衡,与之对称的,RR 可以 由一次左单旋平衡。

    LR 则须 由一次左单旋,先变为LL,再由一次右单旋平衡 。(即一次左右双旋

    RL 与之对称的,一次右左双旋

    详见:

    http://blog.csdn.net/gabriel1026/article/details/6311339

    应用一:动态查询 整颗树中第k大数。

    hdu 4006: http://acm.hdu.edu.cn/showproblem.php?pid=4006

    题意不含删除操作~, O(qlgn)

      1 #include<map>
      2 #include<set>
      3 #include<list>
      4 #include<cmath>
      5 #include<ctime>
      6 #include<queue>
      7 #include<stack>
      8 #include<cctype>
      9 #include<cstdio>
     10 #include<string>
     11 #include<vector>
     12 #include<cstdlib>
     13 #include<cstring>
     14 #include<iostream>
     15 #include<algorithm>
     16 #define MAXN 1000005
     17 #define INF 0x3f3f3f3f
     18 #define LL long long
     19 #define Test() cout<<"Test"<<endl;
     20 #define Debug(a) cout<<#a<<" = "<<a<<endl;
     21 #define Debug2(a,b) cout<<#a<<" = "<<a<<" , "<<#b<<" = "<<b<<endl;
     22 using namespace std;
     23 
     24 struct node{
     25     int v, h;    // v:value, h: hight
     26     int l, r;    // 2 children
     27     int c;        // 树的size, 即节点数
     28 };
     29 typedef struct node AVL;    //inscreasing order
     30 AVL t[MAXN];
     31 int root, ie;
     32 
     33 void init(){
     34     root = 0, ie = 1;
     35     t[0].h = -1;    //以t[0]为空树。
     36     t[0].c = 0;
     37 }
     38 
     39 void pushUp(int p){
     40     int l=t[p].l, r=t[p].r;
     41     t[p].h = max(t[l].h, t[r].h)+1;
     42     t[p].c = t[l].c + t[r].c + 1;
     43 }
     44 
     45 //L(), R() 均为单旋, 以 q 为轴,将p向下旋
     46 void L(int &p){        // p在q的左边, 称之为左单旋
     47     int q=t[p].r, tmp;
     48     t[p].r = t[q].l;
     49     t[q].l = p;
     50     tmp=p, p=q, q=tmp;    //由于此时q为根, swap(p, q)    
     51     pushUp(q);            //先q后p
     52     pushUp(p);
     53 }
     54 
     55 void R(int &p){        // p在q的右边, 称之为右单旋
     56     int q=t[p].l, tmp;
     57     t[p].l = t[q].r;
     58     t[q].r = p;
     59     tmp=p, p=q, q=tmp;        
     60     pushUp(q);    
     61     pushUp(p);
     62 }
     63 /*
     64 void print(int p){
     65     printf(",(");
     66     if(p){
     67         printf("%d", t[p].v);
     68         print(t[p].l);        
     69         print(t[p].r);
     70     }
     71     printf("),");
     72 }
     73 */
     74 void add(int &p, int v, bool f){    //对于重复元素, f=0: 插在left
     75     int l=t[p].l, r=t[p].r;
     76     if(!p){
     77         //printf("added
    ");
     78         t[ie].v=v, t[ie].c=1;
     79         t[ie].h = t[ie].l = t[ie].r=0;
     80         p = ie++;
     81         //return ;
     82     }
     83     else if(v<t[p].v || (v==t[p].v && f==0)){
     84         //printf("left:
    ");
     85         add(l, v, false); t[p].l = l;    //t[p].l本身须被改变
     86         if(t[l].h-t[r].h == 2){
     87             if(v <= t[l].v)
     88                 R(p);
     89             else{
     90                 L(l); t[p].l=l;
     91                 R(p);
     92             }
     93         }
     94     }else if(v>t[p].v || (v==t[p].v && f)){
     95         //printf("right:
    ");
     96         add(r, v, true); t[p].r = r;    //t[p].r本身须被改变    
     97         if(t[r].h-t[l].h == 2){
     98             //printf("r:
    ");
     99             if(v >= t[r].v)
    100                 L(p);
    101             else{
    102                 R(r); t[p].r=r;
    103                 L(p);
    104             } 
    105         }
    106     }else{
    107         ;    //允许重复值
    108     }
    109     pushUp(p);
    110     /*
    111     printf("p : %d
    ", root);
    112     print(p);
    113     printf("
    ");
    114     */
    115 }
    116 
    117 //void remove(){}
    118 
    119 int query(int p, int k){
    120     int l=t[p].l, r=t[p].r; 
    121     if(k == t[l].c+1)
    122         return t[p].v;
    123     else if(k > t[l].c+1)
    124         return query(r, k-(t[l].c+1));
    125     else
    126         return query(l, k);
    127 }
    128 
    129 //hdu 4006
    130 int main()
    131 {
    132     int m, k, x;
    133     while(~scanf("%d%d", &m, &k)){
    134         init();
    135         while(m--){
    136             char s[5];
    137             scanf("%s", s);
    138             if(s[0] == 'I'){
    139                 cin >> x;
    140                 add(root, x, false);
    141             }
    142             else
    143                 printf("%d
    ", query(root, t[root].c+1-k));
    144             
    145         }
    146     }
    147 
    148     return 0;
    149 }
    View Code
  • 相关阅读:
    Mysql数据库的一些操作
    【狂神说Java】JavaWeb入门到实战1---笔记
    图神经网络学习
    HWSX网址
    python如何判断两个数组完全相等?
    SQL-3-菜鸟教程
    SQL-2
    时间序列相似度分析算法
    pip install 安装不了怎么办?
    leetcode 3 无重复字符的最长子串
  • 原文地址:https://www.cnblogs.com/KimKyeYu/p/3458462.html
Copyright © 2011-2022 走看看