Browse Source

Implemented a probably broken balanced remove op

Cameron Weinfurt 5 months ago
parent
commit
1e588644ae
1 changed files with 85 additions and 24 deletions
  1. 85
    24
      tree_alloc.c

+ 85
- 24
tree_alloc.c View File

@@ -159,30 +159,91 @@ void repair_tree_after_insert(TreeAlloc **root_ptr, TreeAlloc *ta) {
159 159
 	}
160 160
 }
161 161
 
162
-// TODO: Rewrite for self-balancing tree.
163
-void remove_node(TreeAlloc** root_ptr, TreeAlloc* node) {
164
-  TreeAlloc *replace = NULL;
165
-  if (node->left == NULL) {
166
-    replace = node->right;
167
-  } else if (node->right != NULL) {
168
-    replace = node->right;
169
-    TreeAlloc *head = node->left;
170
-    while (head->right != NULL) {
171
-      head = head->right;
172
-    }
173
-    head->right = head->parent->right;
174
-    head->right->parent = head;
175
-  }
176
-  if (node->parent == NULL) {
177
-    replace->parent = NULL;
178
-    *root_ptr = replace;
179
-  } else {
180
-    if (node == node->parent->left) {
181
-      node->parent->left = replace;
182
-    } else {
183
-      node->parent->right = replace;
184
-    }
185
-  }
162
+void replace_node(TreeAlloc **root_ptr, TreeAlloc *node, TreeAlloc *replace) {
163
+	if (!node->parent) {
164
+		*root_ptr = replace;
165
+	} else {
166
+		if (node == node->parent->left)
167
+			node->parent->left = replace;
168
+		else 
169
+			node->parent->right = replace;
170
+	}
171
+	if (!replace) replace->parent = node->parent;
172
+}
173
+
174
+void repair_after_remove(TreeAlloc **root_ptr, TreeAlloc *node) {
175
+	if (node->color == COLOR_RED) {
176
+		node->color = COLOR_BLACK;
177
+	} else {
178
+		TreeAlloc *sibling = get_sibling(node);
179
+		if (sibling->color == COLOR_RED) {
180
+			if (node->parent->left == node)
181
+				rotate_left(root_ptr, node->parent);
182
+			else
183
+				rotate_right(root_ptr, node->parent);
184
+			node->parent->parent->color = node->parent->color = COLOR_BLACK;
185
+		} 
186
+
187
+		if (sibling->left->color == COLOR_BLACK && sibling->right->color == COLOR_BLACK) {
188
+			node->color = COLOR_BLACK;
189
+			sibling->color = COLOR_RED;
190
+			repair_after_remove(root_ptr, parent);
191
+		} else {
192
+			if (node->parent->left == node && sibling->right->color == COLOR_BLACK) {
193
+				rotate_right(root_ptr, sibling);
194
+				sibling = get_sibling(node);
195
+				sibling->color = COLOR_RED;
196
+				sibling->right->color = COLOR_RED;
197
+
198
+				rotate_left(root_ptr, parent);
199
+				node->color = get_sibling(node->parent)->color = COLOR_BLACK;
200
+			} else if (node->parent->right == node && sibling->left->color == COLOR_BLACK) {
201
+				rotate_left(root_ptr, sibling);
202
+				sibling = get_sibling(node);
203
+				sibling->color = COLOR_RED;
204
+				sibling->left->color = COLOR_RED;
205
+
206
+				rotate_right(root_ptr, sibling);
207
+				node->color = get_sibling(node->parent)->color = COLOR_BLACK;
208
+			}
209
+			node->parent->color ^= node->parent->parent->color;
210
+			node->parent->parent->color ^= node->parent->color;
211
+			node->parent->color ^= node->parent->parent->color;
212
+		}
213
+	}
214
+}
215
+
216
+void remove_node(TreeAlloc **root_ptr, TreeAlloc *node) {
217
+	char do_repair = 0;
218
+	TreeAlloc *replace;
219
+	TreeAlloc *parent = node->parent;
220
+	if (!node->left) {
221
+		replace = node->right;
222
+		do_fix = node->color == COLOR_BLACK;
223
+		replace_node(root_ptr, node, replace);
224
+	} else if (!node->right) {
225
+		replace = node->left;
226
+		do_fix = node->color == COLOR_BLACK;
227
+		replace_node(root_ptr, node, replace);
228
+	} else {
229
+		TreeAlloc *tmp = node->right;
230
+		while (tmp->left) tmp = tmp->left;
231
+		replace = tmp->right;
232
+		do_fix = tmp == COLOR_BLACK;
233
+		if (tmp != node->right) {
234
+			replace_node(root_ptr, tmp, replace);
235
+			tmp->right = node->right;
236
+			node->right->parent = tmp;
237
+		}
238
+		replace_node(root_ptr, node, tmp);
239
+		tmp->color = node->color;
240
+		tmp->left = node->left;
241
+		node->left->parent = tmp;
242
+	}
243
+
244
+	if (do_repair) {
245
+		repair_after_remove(root_ptr, replace);
246
+	}
186 247
 }
187 248
 
188 249
 

Loading…
Cancel
Save