Splay 伸展树

废话不说,有篇论文可供参考:杨思雨:《伸展树的基本操作与应用》

Splay的好处可以快速分裂和合并。

上代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//Splay的核心操作splay,在每次插入,删除,查找等操作中都要调用,以用来维护树的平衡,具体证明请网上搜索
#include <iostream>
using namespace std;
 
#define NEW(d) new Splay(d)
 
struct Splay {
    Splay* ch[2];
    int key;
    Splay() : key(0) { ch[0] = ch[1] = NULL; }
    Splay(int d) : key(d) { ch[0] = ch[1] = NULL; }
    int cmp(int d) {
        if(key == d) return -1;
        return key > d ? 0 : 1;
    }
}*root = NULL;
 
typedef Splay* tree;
 
//左右旋,这里用的技巧是在lrj白书上看到的,旋转不多说,自己理解
void rot(tree& rt, int d) {
    tree k = rt-> ch[d^1]; rt-> ch[d^1] = k-> ch[d]; k-> ch[d] = rt; rt = k;
}
 
void splay(tree& rt, int d) {
    int k = rt-> cmp(d);
    if(k != -1) {
        tree p = rt-> ch[k];
        int k2 = p-> cmp(d);
        if(k2 != -1) {
            splay(p-> ch[k2], d);
            if(k2 == k) rot(rt, k^1);
            else rot(p, k);
        }
        rot(rt, k^1);
    }
}
 
tree max(tree rt){
    if(rt == NULL) return NULL;
    tree ret = rt;
    while(ret-> ch[1]) ret = ret-> ch[1];
    return ret;
}
 
tree min(tree rt){
    if(rt == NULL) return NULL;
    tree ret = rt;
    while(ret-> ch[0]) ret = ret-> ch[0];
    return ret;
}
 
tree search(tree rt, int d) {
    tree ret = rt;
    while(ret != NULL && ret-> key != d) if(ret-> key > d) ret = ret-> ch[0]; else ret = ret-> ch[1];
    if(ret != NULL) splay(rt, d);
    else return NULL;
    return rt;
}
 
void insert(tree& rt, int d) {
    if(rt == NULL) { rt = NEW(d); splay(root, d);}
    else {
        int p = (rt-> key > d ? 0: 1);
        insert(rt-> ch[p], d);
    }
}
 
void del(tree& rt, int d) {
    if(search(rt, d) == NULL) return;
    tree t;
    if(rt-> ch[0] == NULL) t = rt-> ch[1];
    else {
        t = rt-> ch[0];
        splay(t, max(t)-> key);
        t-> ch[1] = rt-> ch[1];
    }
    delete rt;
    rt = t;
}
 
/*
//合并l和r树,前提是r中元素全部大于l的最大元素
tree merge(tree l, tree r) {
    tree m = max();
    splay(l, m-> key);
    l-> ch[1] = r;
    return l;
}
 
//以rt中节点nod分裂rt树为l树和r树,其中nod属于l树
void split(tree nod, tree rt, tree& l, tree& r) {
    splay(rt, nod-> key);
    l = rt;
    r = rt-> ch[1];
    l-> ch[1] = NULL;
}
 
*/
 
 
void out(string str) {
    cout << str;
}
 
int main() {
    out("1: insert\n2: del\n3: search\n4: max\n5: min\n6: root\n7: Splay\n");
    int c, t;
    tree a;
    while(cin >> c) {
        switch(c) {
        case 1: cin >> t;
                insert(root, t);
                break;
        case 2: cin >> t;
                del(root, t);
                break;
        case 3: cin >> t;
                if(search(root, t) == NULL) out("Not here\n");
                else out("Is here!\n");
                break;
        case 4: a = max(root);
                if(a != NULL) cout << a-> key << endl;
                else out("Warn!\n");
                break;
        case 5: a = min(root);
                if(a != NULL) cout << a-> key << endl;
                else out("Warn!\n");
                break;
        case 6: if(root != NULL) { out("root is: "); cout << root-> key << endl; }
                else out("Warn!\n");
                break;
        case 7: cin >> t;
                a = search(root, t);
                if(a == NULL) out("Not here\n");
                else splay(root, t);
                break;
        default:
                break;
        }
    }
    return 0;
}

Splay 伸展树

上一篇:使用Lingo增强JMS


下一篇:Lingo