-
Notifications
You must be signed in to change notification settings - Fork 1
/
tree.c
174 lines (155 loc) · 3.97 KB
/
tree.c
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#include "tree.h"
#include "malloc.h"
static inline struct tree_node *grandparent(struct tree_node *n) {
return n->parent->parent;
}
static inline struct tree_node *uncle(struct tree_node *n) {
if (n->parent == grandparent(n)->left)
return grandparent(n)->right;
else
return grandparent(n)->left;
}
static inline void rotate_left(struct tree_node *p) {
struct tree_node *c = p->right;
p->right = c->left;
if (p->right) {
p->right->parent = p;
p->right->pparent = &p->right;
}
c->left = p;
c->parent = p->parent;
p->parent = c;
c->pparent = p->pparent;
*(c->pparent) = c;
p->pparent = &c->left;
}
static inline void rotate_right(struct tree_node *p) {
struct tree_node *c = p->left;
p->left = c->right;
if (p->left) {
p->left->parent = p;
p->left->pparent = &p->left;
}
c->right = p;
c->parent = p->parent;
p->parent = c;
c->pparent = p->pparent;
*(c->pparent) = c;
p->pparent = &c->right;
}
static void insert_case5(struct tree_node *n) {
n->parent->color = BLACK;
grandparent(n)->color = RED;
if (n == n->parent->left && n->parent == grandparent(n)->left)
rotate_right(grandparent(n));
else
rotate_left(grandparent(n));
}
static void insert_case4(struct tree_node *n) {
if (n == n->parent->right && n->parent == grandparent(n)->left) {
rotate_left(n->parent);
n = n->left;
} else if (n == n->parent->left && n->parent == grandparent(n)->right) {
rotate_right(n->parent);
n = n->right;
}
insert_case5(n);
}
static void insert_case1(struct tree_node *n);
/* avoid compile warning */
static void insert_case3(struct tree_node *n) {
if (uncle(n) != NULL && uncle(n)->color == RED) {
n->parent->color = BLACK;
uncle(n)->color = BLACK;
grandparent(n)->color = RED;
insert_case1(grandparent(n));
} else
insert_case4(n);
}
static void insert_case2(struct tree_node *n) {
if (n->parent->color == BLACK)
return;
else
insert_case3(n);
}
static void insert_case1(struct tree_node *n) {
if (n->parent == NULL)
n->color = BLACK;
else
insert_case2(n);
}
/* return 1 for found, 0 for none */
int tree_find(struct tree_node *root, const char *str, struct exp **rtn) {
struct tree_node *p = root;
int cmp;
while (p) {
cmp = strcmp(str, p->sym->sym);
if (cmp > 0)
p = p->right;
else if (cmp < 0)
p = p->left;
else {
*rtn = p->value;
return 1;
}
}
return 0;
}
/* *
* return value: 0 if have inserted successfully, 1 if *failed* at insert
* if `replace' is
* 0: do not permit replacement
* 1: must replace, do not alloc new node, this is for set_in_env
*/
int tree_insert(struct tree_node **root, struct symbol *sym, struct exp *e, int replace) {
struct tree_node **cur;
struct tree_node *p;
struct tree_node *parent;
int cmp;
for (cur = root, parent = NULL; *cur;) {
p = *cur;
cmp = strcmp(sym->sym, p->sym->sym);
if (cmp > 0) {
parent = p;
cur = &p->right;
} else if (cmp < 0) {
parent = p;
cur = &p->left;
} else {
if (replace) {
/* overwrite */
p->value = e;
return 0;
}
return 1;
}
}
if (replace)
return 1;
*cur = alloc_tree_node(parent, cur, sym, e);
insert_case1(*cur);
return 0;
}
/* code below is for debugging */
typedef void (*handler_fn)(struct tree_node *);
static void traverse(struct tree_node *p, handler_fn handler) {
handler(p);
if (p->left)
traverse(p->left, handler);
if (p->right)
traverse(p->right, handler);
}
static void to_dot(struct tree_node *cur) {
if (cur->left != NULL)
fprintf(stderr, "\t\"%s\" -> \"%s\"[headport=n, tailport=sw]\n", cur->sym->sym, cur->left->sym->sym);
if (cur->parent != NULL)
fprintf(stderr, "\t\"%s\" -> \"%s\"[headport=s, tailport=n]\n", cur->sym->sym, cur->parent->sym->sym);
fprintf(stderr, "\t\"%s\"[color=%s]\n", cur->sym->sym, (cur->color == RED)?"red":"black");
if (cur->right != NULL)
fprintf(stderr, "\t\"%s\" -> \"%s\"[headport=n, tailport=se]\n", cur->sym->sym, cur->right->sym->sym);
}
void dump(struct tree_node *root) {
fprintf(stderr, "digraph heaptree{\n");
traverse(root, to_dot);
fprintf(stderr, "}\n");
}