scapegoateTree

scapegoat Tree

替罪羊树,他是一个暴力的bst,与普通bst相比,他记录了子树的大小,用参数alpha来定义平衡,即左右子树的大小都不允许超过根的alpha倍,所以往往aplha是一个0.5到1的数字,当违反了这个性质,就暴力重构,将树构造为完全平衡树。 ## 替罪羊树erase 为节点打上标记scapegoat,代表这个节点已经被删除了,回溯子树大小信息。 ## 替罪羊树insert 使用bst插入的方式来插入,注意特判掉那些被打删除标记的点,就可以了 ## 替罪羊树重构 当我们erase或者insert以后,受影响的节点应该恰好构成了一条从根到目标的链,我们使用maintain来重新调整子树大小的时候,注意标记那些非法(不平衡)的节点,然后当我们maintain到根的时候,我们重构离根最近的不平衡的子树。 ## 替罪羊树代码
替罪羊树代码
treeview raw
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
#pragma once
#include "../memery_management/memery_pool.h"
#include "search_tree.h"
#include "vector.h"

namespace data_structure {
template <class T>
class scapegoat_tree : public search_tree<T> {
struct node {
node *ls, *rs;
int siz, scapegoat;
T key;
};
static const double alpha;
memery_pool<node> pool;
node* root = nullptr;
void copy_self(node*& rt, node* cp) {
if (cp == nullptr) return;
rt = pool.get();
*rt = *cp;
copy_self(rt->ls, cp->ls);
copy_self(rt->rs, cp->rs);
}
void delete_self(node* rt) {
if (rt == nullptr) return;
delete_self(rt->ls);
delete_self(rt->rs);
pool.erase(rt);
}
node* newnode(const T& w) {
node* res = pool.get();
res->ls = res->rs = nullptr;
res->key = w;
res->siz = 1;
res->scapegoat = 0;
return res;
}
void make_list(node* rt, vector<node*>& array) {
if (rt == nullptr) return;
make_list(rt->ls, array);
if (!rt->scapegoat) array.push_back(rt);
make_list(rt->rs, array);
if (rt->scapegoat) pool.erase(rt);
}
void build_dfs(node*& rt, vector<node*>& array, int l, int r) {
if (l > r) {
rt = nullptr;
return;
}
int mid = l + r >> 1;
rt = array[mid];
build_dfs(rt->ls, array, l, mid - 1);
build_dfs(rt->rs, array, mid + 1, r);
maintain(rt);
}
void rebuild(node*& rt) {
vector<node*> array;
make_list(rt, array);
build_dfs(rt, array, 0, array.size() - 1);
}
void maintain(node*& rt) {
int lsiz = rt->ls == nullptr ? 0 : rt->ls->siz;
int rsiz = rt->rs == nullptr ? 0 : rt->rs->siz;
rt->siz = lsiz + rsiz + 1;
if (rt->scapegoat) rt->siz--;
static node** prt = nullptr; //记录路径上离根最近的不平衡的子树
if (lsiz > alpha * rt->siz || rsiz > alpha * rt->siz) prt = &rt;
if (rt == root && prt != nullptr) {
node** tem = prt;
prt = nullptr;
rebuild(*tem);
}
}
void insert(node*& rt, const T& w) {
if (rt == nullptr)
rt = newnode(w);
else if (w < rt->key)
insert(rt->ls, w);
else if (rt->key < w)
insert(rt->rs, w);
else if (rt->scapegoat) {
rt->scapegoat = 0;
}
maintain(rt);
}
node*& search(node*& rt, const T& w) {}
void erase(node*& rt, const T& w) {
if (rt == nullptr) {
return;
} else if (w < rt->key) {
erase(rt->ls, w);
} else if (rt->key < w) {
erase(rt->rs, w);
} else {
rt->scapegoat = 1;
}
maintain(rt);
}
void preorder(node*& rt, void (*f)(const T&)) {
if (rt == nullptr) return;
if (!rt->scapegoat) f(rt->key);
preorder(rt->ls, f);
preorder(rt->rs, f);
}
void midorder(node*& rt, void (*f)(const T&)) {
if (rt == nullptr) return;
midorder(rt->ls, f);
if (!rt->scapegoat) f(rt->key);
midorder(rt->rs, f);
}

public:
// 构造函数和析构函数
scapegoat_tree() { root = nullptr; }
scapegoat_tree(const scapegoat_tree<T>& rhs) { copy_self(root, rhs.root); }
scapegoat_tree<T> operator=(const scapegoat_tree<T>& rhs) {
delete_self(root);
copy_self(root, rhs.root);
return *this;
}
~scapegoat_tree() { delete_self(root); }

//普通操作
void insert(const T& w) { insert(root, w); }
node*& search(const T& w) { return search(root, w); }
void erase(const T& w) { erase(root, w); }
void preorder(void (*f)(const T&)) { preorder(root, f); }
void midorder(void (*f)(const T&)) { midorder(root, f); }
};

template<class T>
const double scapegoat_tree<T>::alpha = 0.7;
} // namespace data_structure