libtrbase
1.0.2
Web server and task management solution.
Main Page
Related Pages
Data Structures
Files
File List
Globals
tree_macros.h
Go to the documentation of this file.
1
/**
2
* \file
3
*
4
* \author Georg Hopp
5
*
6
* \copyright
7
* Copyright © 2014 Georg Hopp
8
*
9
* This program is free software: you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation, either version 3 of the License, or
12
* (at your option) any later version.
13
*
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
18
*
19
* You should have received a copy of the GNU General Public License
20
* along with this program. If not, see <http://www.gnu.org/licenses/>.
21
*/
22
23
#ifndef __TR_TREE_MACROS_H__
24
#define __TR_TREE_MACROS_H__
25
26
#include "
trbase.h
"
27
28
#define TR_TREE_RIGHT(node) (NULL!=(node)?(node)->right:NULL)
29
#define TR_TREE_LEFT(node) (NULL!=(node)?(node)->left:NULL)
30
#define TR_TREE_PARENT(node) (NULL!=(node)?(node)->parent:NULL)
31
32
#define TR_TREE_CHILD(node) \
33
(NULL==TR_TREE_RIGHT((node))?TR_TREE_LEFT((node)):TR_TREE_RIGHT((node)))
34
35
#define TR_TREE_SIBLING(node) \
36
(NULL!=(node)->parent? \
37
((node)==(node)->parent->left? \
38
(node)->parent->right: \
39
(node)->parent->left): \
40
NULL)
41
42
#define TR_TREE_UNCLE(node) \
43
((node)->parent == (node)->parent->parent->left \
44
? (node)->parent->parent->right \
45
: (node)->parent->parent->left)
46
47
#define TR_TREE_REPLACE_NODE(root, node1, node2) \
48
if (NULL != (node1)->parent) { \
49
if ((node1) == (node1)->parent->left) { \
50
(node1)->parent->left = (node2); \
51
} else { \
52
(node1)->parent->right = (node2); \
53
} \
54
} else { \
55
*(root) = (node2); \
56
} \
57
if (NULL != (node2)) { \
58
(node2)->parent = (node1)->parent; \
59
}
60
61
#define TR_TREE_ROT_RCLD_right(node) ((node)->left)
62
#define TR_TREE_ROT_RCLD_left(node) ((node)->right)
63
64
#define TR_TREE_ROTATE(lr, root, node) \
65
if (NULL != (node)) { \
66
void * stPar = node->parent; \
67
void * relCld = TR_TREE_ROT_RCLD_##lr(node); \
68
void * relCCld = TR_TREE_ROT_RCLD_##lr(node)->lr; \
69
void * nLeft_p = &TR_TREE_ROT_RCLD_##lr(node); \
70
if (NULL != relCCld) { \
71
TR_TREE_ROT_RCLD_##lr(node)->lr->parent = node; \
72
} \
73
TR_TREE_ROT_RCLD_##lr(node)->lr = node; \
74
if (NULL != node->parent) { \
75
if (node->parent->left == node) { \
76
node->parent->left = relCld; \
77
} else { \
78
node->parent->right = relCld; \
79
} \
80
} else { \
81
*(root) = relCld; \
82
} \
83
node->parent = relCld; \
84
TR_TREE_ROT_RCLD_##lr(node)->parent = stPar; \
85
*(void**)nLeft_p = relCCld; \
86
}
87
88
typedef
enum
{
rbBlack
=1,
rbRed
=2}
TR_rbColor
;
89
90
#define TR_TREE_NODE_BLACK(node) \
91
(NULL == (node) || rbBlack == (node)->color)
92
#define TR_TREE_NODE_RED(node) \
93
(NULL == (node) || rbRed == (node)->color)
94
#define TR_TREE_NODE_STRICT_BLACK(node) \
95
(NULL != (node) && rbBlack == (node)->color)
96
#define TR_TREE_NODE_STRICT_RED(node) \
97
(NULL != (node) && rbRed == (node)->color)
98
99
#define TR_TREE_INORDER_SUCC(node, succ) \
100
succ = (node)->right; \
101
while (NULL != succ->left) { \
102
succ = succ->left; \
103
}
104
105
/*
106
* Find data in a tree.
107
* Attention: This will change node, so normally you need to copy
108
* it before using this macro.
109
* Also be aware that found needs to be a valid lvalue and an integer.
110
*/
111
#define TR_TREE_FIND(node, search, found, comp) \
112
(found) = -1; \
113
if ((node)) { \
114
while (1) { \
115
(found) = (comp)((node)->data, (search)); \
116
if (0 != (found)) { \
117
if (0 < (found)) { \
118
if (! (node)->left) break; \
119
(node) = (node)->left; \
120
} else { \
121
if (! (node)->right) break; \
122
(node) = (node)->right; \
123
} \
124
} else { \
125
break; \
126
} \
127
} \
128
}
129
130
#define TR_TREE_BALANCE_DELETE_CASE1(node) \
131
if (NULL == (node)->parent) { \
132
break; \
133
}
134
135
#define TR_TREE_BALANCE_DELETE_CASE2(root, node, sibling) \
136
if (NULL != (sibling) && rbRed == (sibling)->color) { \
137
(node)->parent->color = rbRed; \
138
(sibling)->color = rbBlack; \
139
if (NULL != (node)->parent->right \
140
&& (node) != (node)->parent->right) { \
141
TR_TREE_ROTATE(left, (root), (node)->parent); \
142
} else { \
143
TR_TREE_ROTATE(right, (root), (node)->parent); \
144
} \
145
(sibling) = TR_TREE_SIBLING((node)); \
146
}
147
148
#define TR_TREE_BALANCE_DELETE_CASE34(root, node, sibling) \
149
if (NULL == (sibling) \
150
|| (rbBlack == (sibling)->color \
151
&& TR_TREE_NODE_BLACK((sibling)->left) \
152
&& TR_TREE_NODE_BLACK((sibling)->right))) { \
153
if (NULL != (sibling)) { \
154
(sibling)->color = rbRed; \
155
} \
156
if (rbBlack == (node)->parent->color) { \
157
(node) = (node)->parent; \
158
continue; \
159
} else { \
160
(node)->parent->color = rbBlack; \
161
break; \
162
} \
163
}
164
165
/*
166
* this if statement is trivial,
167
* due to case 2 (even though case 2 changed the sibling to a
168
* sibling's child,
169
* the sibling's child can't be red, since no red parent can
170
* have a red child).
171
*
172
* the following statements just force the red to be on the
173
* left of the left of the parent,
174
* or right of the right, so case 6 will rotate correctly.
175
*/
176
#define TR_TREE_BALANCE_DELETE_CASE5(root, node, sibling) \
177
if (NULL != (sibling) && rbBlack == (sibling)->color) { \
178
if ((node) == (node)->parent->left \
179
&& TR_TREE_NODE_BLACK((sibling)->right) \
180
&& TR_TREE_NODE_STRICT_RED((sibling)->left)) { \
181
(sibling)->color = rbRed; \
182
(sibling)->left->color = rbBlack; \
183
TR_TREE_ROTATE(right, (root), (sibling)); \
184
} else if ((node) == (node)->parent->right \
185
&& TR_TREE_NODE_BLACK((sibling)->left) \
186
&& TR_TREE_NODE_STRICT_RED((sibling)->right)) { \
187
(sibling)->color = rbRed; \
188
(sibling)->right->color = rbBlack; \
189
TR_TREE_ROTATE(left, (root), (sibling)); \
190
} \
191
(sibling) = TR_TREE_SIBLING((node)); \
192
}
193
194
#define TR_TREE_BALANCE_DELETE_CASE6(root, node, sibling) \
195
if (NULL != (sibling)) { \
196
(sibling)->color = (node)->parent->color; \
197
} \
198
if (NULL != (node) && NULL != (node)->parent) { \
199
(node)->parent->color = rbBlack; \
200
if (NULL != (node)->parent->right \
201
&& (node) != (node)->parent->right) { \
202
if (NULL != (sibling)->right) { \
203
(sibling)->right->color = rbBlack; \
204
} \
205
TR_TREE_ROTATE(left, (root), (node)->parent); \
206
} else { \
207
if (NULL != (sibling)->left) { \
208
(sibling)->left->color = rbBlack; \
209
} \
210
TR_TREE_ROTATE(right, (root), (node)->parent); \
211
} \
212
}
213
214
#define TR_TREE_BALANCE_DELETE(root, node, sibling) \
215
while(1) { \
216
TR_TREE_BALANCE_DELETE_CASE1((node)) \
217
sibling = TR_TREE_SIBLING(node); \
218
TR_TREE_BALANCE_DELETE_CASE2((root), (node), (sibling)) \
219
TR_TREE_BALANCE_DELETE_CASE34((root), (node), (sibling)) \
220
TR_TREE_BALANCE_DELETE_CASE5((root), (node), (sibling)) \
221
TR_TREE_BALANCE_DELETE_CASE6((root), (node), (sibling)) \
222
break; \
223
}
224
225
#define TR_TREE_BALANCE_INSERT_CASE1(node) \
226
if (NULL == (node)->parent) { \
227
(node)->color = rbBlack; \
228
break; \
229
}
230
231
#define TR_TREE_BALANCE_INSERT_CASE2(node) \
232
if (rbBlack == (node)->parent->color) { \
233
break; \
234
}
235
236
#define TR_TREE_BALANCE_INSERT_CASE3(node) \
237
if (NULL != TR_TREE_UNCLE(node) \
238
&& rbRed == TR_TREE_UNCLE(node)->color) { \
239
(node)->parent->color = rbBlack; \
240
TR_TREE_UNCLE(node)->color = rbBlack; \
241
(node)->parent->parent->color = rbRed; \
242
(node) = (node)->parent->parent; \
243
continue; \
244
}
245
246
#define TR_TREE_BALANCE_INSERT_CASE4(root, node) \
247
if ((node) == (node)->parent->right \
248
&& (node)->parent == (node)->parent->parent->left) { \
249
TR_TREE_ROTATE(left, (root), (node)->parent); \
250
(node) = (node)->left; \
251
} else if ((node) == (node)->parent->left \
252
&& (node)->parent == (node)->parent->parent->right) { \
253
TR_TREE_ROTATE(right, (root), (node)->parent); \
254
(node) = (node)->right; \
255
}
256
257
#define TR_TREE_BALANCE_INSERT_CASE5(root, node) \
258
(node)->parent->color = rbBlack; \
259
(node)->parent->parent->color = rbRed; \
260
if ((node) == (node)->parent->left) { \
261
TR_TREE_ROTATE(right, (root), (node)->parent->parent); \
262
} else { \
263
TR_TREE_ROTATE(left, (root), (node)->parent->parent); \
264
}
265
266
#define TR_TREE_BALANCE_INSERT(root, node) \
267
while (1) { \
268
TR_TREE_BALANCE_INSERT_CASE1((node)) \
269
TR_TREE_BALANCE_INSERT_CASE2((node)) \
270
if (NULL != (node)->parent->parent) { \
271
TR_TREE_BALANCE_INSERT_CASE3((node)) \
272
TR_TREE_BALANCE_INSERT_CASE4((root), (node)) \
273
TR_TREE_BALANCE_INSERT_CASE5((root), (node)) \
274
} \
275
break; \
276
}
277
278
#endif // __TR_TREE_MACROS_H__
279
280
// vim: set ts=4 sw=4:
TR_rbColor
TR_rbColor
Definition:
tree_macros.h:88
rbRed
Definition:
tree_macros.h:88
rbBlack
Definition:
tree_macros.h:88
trbase.h
include
tr
tree_macros.h
Generated on Tue Apr 12 2016 10:15:56 for libtrbase by
1.8.10