Mercurial > hg > octave-kai > gnulib-hg
comparison lib/gl_anyavltree_list2.h @ 12421:e8d2c6fc33ad
Use spaces for indentation, not tabs.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Thu, 10 Dec 2009 20:28:30 +0100 |
parents | bbbbbf4cd1c5 |
children | a8c91b846640 |
comparison
equal
deleted
inserted
replaced
12420:5850b9a81029 | 12421:e8d2c6fc33ad |
---|---|
58 return node; | 58 return node; |
59 } | 59 } |
60 | 60 |
61 static gl_list_t | 61 static gl_list_t |
62 gl_tree_create (gl_list_implementation_t implementation, | 62 gl_tree_create (gl_list_implementation_t implementation, |
63 gl_listelement_equals_fn equals_fn, | 63 gl_listelement_equals_fn equals_fn, |
64 gl_listelement_hashcode_fn hashcode_fn, | 64 gl_listelement_hashcode_fn hashcode_fn, |
65 gl_listelement_dispose_fn dispose_fn, | 65 gl_listelement_dispose_fn dispose_fn, |
66 bool allow_duplicates, | 66 bool allow_duplicates, |
67 size_t count, const void **contents) | 67 size_t count, const void **contents) |
68 { | 68 { |
69 struct gl_list_impl *list = XMALLOC (struct gl_list_impl); | 69 struct gl_list_impl *list = XMALLOC (struct gl_list_impl); |
70 | 70 |
71 list->base.vtable = implementation; | 71 list->base.vtable = implementation; |
72 list->base.equals_fn = equals_fn; | 72 list->base.equals_fn = equals_fn; |
87 list->root = create_subtree_with_contents (count, contents); | 87 list->root = create_subtree_with_contents (count, contents); |
88 list->root->parent = NULL; | 88 list->root->parent = NULL; |
89 | 89 |
90 #if WITH_HASHTABLE | 90 #if WITH_HASHTABLE |
91 /* Now that the tree is built, node_position() works. Now we can | 91 /* Now that the tree is built, node_position() works. Now we can |
92 add the nodes to the hash table. */ | 92 add the nodes to the hash table. */ |
93 add_nodes_to_buckets (list); | 93 add_nodes_to_buckets (list); |
94 #endif | 94 #endif |
95 } | 95 } |
96 else | 96 else |
97 list->root = NULL; | 97 list->root = NULL; |
103 The height of NODE is incremented by HEIGHT_DIFF (1 or -1). | 103 The height of NODE is incremented by HEIGHT_DIFF (1 or -1). |
104 PARENT = NODE->parent. (NODE can also be NULL. But PARENT is non-NULL.) | 104 PARENT = NODE->parent. (NODE can also be NULL. But PARENT is non-NULL.) |
105 Rotation operations are performed starting at PARENT (not NODE itself!). */ | 105 Rotation operations are performed starting at PARENT (not NODE itself!). */ |
106 static void | 106 static void |
107 rebalance (gl_list_t list, | 107 rebalance (gl_list_t list, |
108 gl_list_node_t node, int height_diff, gl_list_node_t parent) | 108 gl_list_node_t node, int height_diff, gl_list_node_t parent) |
109 { | 109 { |
110 for (;;) | 110 for (;;) |
111 { | 111 { |
112 gl_list_node_t child; | 112 gl_list_node_t child; |
113 int previous_balance; | 113 int previous_balance; |
119 node = parent; | 119 node = parent; |
120 | 120 |
121 previous_balance = node->balance; | 121 previous_balance = node->balance; |
122 | 122 |
123 /* The balance of NODE is incremented by BALANCE_DIFF: +1 if the right | 123 /* The balance of NODE is incremented by BALANCE_DIFF: +1 if the right |
124 branch's height has increased by 1 or the left branch's height has | 124 branch's height has increased by 1 or the left branch's height has |
125 decreased by 1, -1 if the right branch's height has decreased by 1 or | 125 decreased by 1, -1 if the right branch's height has decreased by 1 or |
126 the left branch's height has increased by 1, 0 if no height change. */ | 126 the left branch's height has increased by 1, 0 if no height change. */ |
127 if (node->left != NULL || node->right != NULL) | 127 if (node->left != NULL || node->right != NULL) |
128 balance_diff = (child == node->right ? height_diff : -height_diff); | 128 balance_diff = (child == node->right ? height_diff : -height_diff); |
129 else | 129 else |
130 /* Special case where above formula doesn't work, because the caller | 130 /* Special case where above formula doesn't work, because the caller |
131 didn't tell whether node's left or right branch shrunk from height 1 | 131 didn't tell whether node's left or right branch shrunk from height 1 |
132 to NULL. */ | 132 to NULL. */ |
133 balance_diff = - previous_balance; | 133 balance_diff = - previous_balance; |
134 | 134 |
135 node->balance += balance_diff; | 135 node->balance += balance_diff; |
136 if (balance_diff == previous_balance) | 136 if (balance_diff == previous_balance) |
137 { | 137 { |
138 /* node->balance is outside the range [-1,1]. Must rotate. */ | 138 /* node->balance is outside the range [-1,1]. Must rotate. */ |
139 gl_list_node_t *nodep; | 139 gl_list_node_t *nodep; |
140 | 140 |
141 if (node->parent == NULL) | 141 if (node->parent == NULL) |
142 /* node == list->root */ | 142 /* node == list->root */ |
143 nodep = &list->root; | 143 nodep = &list->root; |
144 else if (node->parent->left == node) | 144 else if (node->parent->left == node) |
145 nodep = &node->parent->left; | 145 nodep = &node->parent->left; |
146 else if (node->parent->right == node) | 146 else if (node->parent->right == node) |
147 nodep = &node->parent->right; | 147 nodep = &node->parent->right; |
148 else | 148 else |
149 abort (); | 149 abort (); |
150 | 150 |
151 nodeleft = node->left; | 151 nodeleft = node->left; |
152 noderight = node->right; | 152 noderight = node->right; |
153 | 153 |
154 if (balance_diff < 0) | 154 if (balance_diff < 0) |
155 { | 155 { |
156 /* node->balance = -2. The subtree is heavier on the left side. | 156 /* node->balance = -2. The subtree is heavier on the left side. |
157 Rotate from left to right: | 157 Rotate from left to right: |
158 | 158 |
159 * | 159 * |
160 / \ | 160 / \ |
161 h+2 h | 161 h+2 h |
162 */ | 162 */ |
163 gl_list_node_t nodeleftleft = nodeleft->left; | 163 gl_list_node_t nodeleftleft = nodeleft->left; |
164 gl_list_node_t nodeleftright = nodeleft->right; | 164 gl_list_node_t nodeleftright = nodeleft->right; |
165 if (nodeleft->balance <= 0) | 165 if (nodeleft->balance <= 0) |
166 { | 166 { |
167 /* | 167 /* |
168 * h+2|h+3 | 168 * h+2|h+3 |
169 / \ / \ | 169 / \ / \ |
170 h+2 h --> / h+1|h+2 | 170 h+2 h --> / h+1|h+2 |
171 / \ | / \ | 171 / \ | / \ |
172 h+1 h|h+1 h+1 h|h+1 h | 172 h+1 h|h+1 h+1 h|h+1 h |
173 */ | 173 */ |
174 node->left = nodeleftright; | 174 node->left = nodeleftright; |
175 nodeleft->right = node; | 175 nodeleft->right = node; |
176 | 176 |
177 nodeleft->parent = node->parent; | 177 nodeleft->parent = node->parent; |
178 node->parent = nodeleft; | 178 node->parent = nodeleft; |
179 if (nodeleftright != NULL) | 179 if (nodeleftright != NULL) |
180 nodeleftright->parent = node; | 180 nodeleftright->parent = node; |
181 | 181 |
182 nodeleft->balance += 1; | 182 nodeleft->balance += 1; |
183 node->balance = - nodeleft->balance; | 183 node->balance = - nodeleft->balance; |
184 | 184 |
185 node->branch_size = | 185 node->branch_size = |
186 (nodeleftright != NULL ? nodeleftright->branch_size : 0) | 186 (nodeleftright != NULL ? nodeleftright->branch_size : 0) |
187 + 1 + (noderight != NULL ? noderight->branch_size : 0); | 187 + 1 + (noderight != NULL ? noderight->branch_size : 0); |
188 nodeleft->branch_size = | 188 nodeleft->branch_size = |
189 nodeleftleft->branch_size + 1 + node->branch_size; | 189 nodeleftleft->branch_size + 1 + node->branch_size; |
190 | 190 |
191 *nodep = nodeleft; | 191 *nodep = nodeleft; |
192 height_diff = (height_diff < 0 | 192 height_diff = (height_diff < 0 |
193 ? /* noderight's height had been decremented from | 193 ? /* noderight's height had been decremented from |
194 h+1 to h. The subtree's height changes from | 194 h+1 to h. The subtree's height changes from |
195 h+3 to h+2|h+3. */ | 195 h+3 to h+2|h+3. */ |
196 nodeleft->balance - 1 | 196 nodeleft->balance - 1 |
197 : /* nodeleft's height had been incremented from | 197 : /* nodeleft's height had been incremented from |
198 h+1 to h+2. The subtree's height changes from | 198 h+1 to h+2. The subtree's height changes from |
199 h+2 to h+2|h+3. */ | 199 h+2 to h+2|h+3. */ |
200 nodeleft->balance); | 200 nodeleft->balance); |
201 } | 201 } |
202 else | 202 else |
203 { | 203 { |
204 /* | 204 /* |
205 * h+2 | 205 * h+2 |
206 / \ / \ | 206 / \ / \ |
207 h+2 h --> h+1 h+1 | 207 h+2 h --> h+1 h+1 |
208 / \ / \ / \ | 208 / \ / \ / \ |
209 h h+1 h L R h | 209 h h+1 h L R h |
210 / \ | 210 / \ |
211 L R | 211 L R |
212 | 212 |
213 */ | 213 */ |
214 gl_list_node_t L = nodeleft->right = nodeleftright->left; | 214 gl_list_node_t L = nodeleft->right = nodeleftright->left; |
215 gl_list_node_t R = node->left = nodeleftright->right; | 215 gl_list_node_t R = node->left = nodeleftright->right; |
216 nodeleftright->left = nodeleft; | 216 nodeleftright->left = nodeleft; |
217 nodeleftright->right = node; | 217 nodeleftright->right = node; |
218 | 218 |
219 nodeleftright->parent = node->parent; | 219 nodeleftright->parent = node->parent; |
220 if (L != NULL) | 220 if (L != NULL) |
221 L->parent = nodeleft; | 221 L->parent = nodeleft; |
222 if (R != NULL) | 222 if (R != NULL) |
223 R->parent = node; | 223 R->parent = node; |
224 nodeleft->parent = nodeleftright; | 224 nodeleft->parent = nodeleftright; |
225 node->parent = nodeleftright; | 225 node->parent = nodeleftright; |
226 | 226 |
227 nodeleft->balance = (nodeleftright->balance > 0 ? -1 : 0); | 227 nodeleft->balance = (nodeleftright->balance > 0 ? -1 : 0); |
228 node->balance = (nodeleftright->balance < 0 ? 1 : 0); | 228 node->balance = (nodeleftright->balance < 0 ? 1 : 0); |
229 nodeleftright->balance = 0; | 229 nodeleftright->balance = 0; |
230 | 230 |
231 nodeleft->branch_size = | 231 nodeleft->branch_size = |
232 (nodeleft->left != NULL ? nodeleft->left->branch_size : 0) | 232 (nodeleft->left != NULL ? nodeleft->left->branch_size : 0) |
233 + 1 + (nodeleft->right != NULL ? nodeleft->right->branch_size : 0); | 233 + 1 + (nodeleft->right != NULL ? nodeleft->right->branch_size : 0); |
234 node->branch_size = | 234 node->branch_size = |
235 (node->left != NULL ? node->left->branch_size : 0) | 235 (node->left != NULL ? node->left->branch_size : 0) |
236 + 1 + (node->right != NULL ? node->right->branch_size : 0); | 236 + 1 + (node->right != NULL ? node->right->branch_size : 0); |
237 nodeleftright->branch_size = | 237 nodeleftright->branch_size = |
238 nodeleft->branch_size + 1 + node->branch_size; | 238 nodeleft->branch_size + 1 + node->branch_size; |
239 | 239 |
240 *nodep = nodeleftright; | 240 *nodep = nodeleftright; |
241 height_diff = (height_diff < 0 | 241 height_diff = (height_diff < 0 |
242 ? /* noderight's height had been decremented from | 242 ? /* noderight's height had been decremented from |
243 h+1 to h. The subtree's height changes from | 243 h+1 to h. The subtree's height changes from |
244 h+3 to h+2. */ | 244 h+3 to h+2. */ |
245 -1 | 245 -1 |
246 : /* nodeleft's height had been incremented from | 246 : /* nodeleft's height had been incremented from |
247 h+1 to h+2. The subtree's height changes from | 247 h+1 to h+2. The subtree's height changes from |
248 h+2 to h+2. */ | 248 h+2 to h+2. */ |
249 0); | 249 0); |
250 } | 250 } |
251 } | 251 } |
252 else | 252 else |
253 { | 253 { |
254 /* node->balance = 2. The subtree is heavier on the right side. | 254 /* node->balance = 2. The subtree is heavier on the right side. |
255 Rotate from right to left: | 255 Rotate from right to left: |
256 | 256 |
257 * | 257 * |
258 / \ | 258 / \ |
259 h h+2 | 259 h h+2 |
260 */ | 260 */ |
261 gl_list_node_t noderightleft = noderight->left; | 261 gl_list_node_t noderightleft = noderight->left; |
262 gl_list_node_t noderightright = noderight->right; | 262 gl_list_node_t noderightright = noderight->right; |
263 if (noderight->balance >= 0) | 263 if (noderight->balance >= 0) |
264 { | 264 { |
265 /* | 265 /* |
266 * h+2|h+3 | 266 * h+2|h+3 |
267 / \ / \ | 267 / \ / \ |
268 h h+2 --> h+1|h+2 \ | 268 h h+2 --> h+1|h+2 \ |
269 / \ / \ | | 269 / \ / \ | |
270 h|h+1 h+1 h h|h+1 h+1 | 270 h|h+1 h+1 h h|h+1 h+1 |
271 */ | 271 */ |
272 node->right = noderightleft; | 272 node->right = noderightleft; |
273 noderight->left = node; | 273 noderight->left = node; |
274 | 274 |
275 noderight->parent = node->parent; | 275 noderight->parent = node->parent; |
276 node->parent = noderight; | 276 node->parent = noderight; |
277 if (noderightleft != NULL) | 277 if (noderightleft != NULL) |
278 noderightleft->parent = node; | 278 noderightleft->parent = node; |
279 | 279 |
280 noderight->balance -= 1; | 280 noderight->balance -= 1; |
281 node->balance = - noderight->balance; | 281 node->balance = - noderight->balance; |
282 | 282 |
283 node->branch_size = | 283 node->branch_size = |
284 (nodeleft != NULL ? nodeleft->branch_size : 0) | 284 (nodeleft != NULL ? nodeleft->branch_size : 0) |
285 + 1 + (noderightleft != NULL ? noderightleft->branch_size : 0); | 285 + 1 + (noderightleft != NULL ? noderightleft->branch_size : 0); |
286 noderight->branch_size = | 286 noderight->branch_size = |
287 node->branch_size + 1 + noderightright->branch_size; | 287 node->branch_size + 1 + noderightright->branch_size; |
288 | 288 |
289 *nodep = noderight; | 289 *nodep = noderight; |
290 height_diff = (height_diff < 0 | 290 height_diff = (height_diff < 0 |
291 ? /* nodeleft's height had been decremented from | 291 ? /* nodeleft's height had been decremented from |
292 h+1 to h. The subtree's height changes from | 292 h+1 to h. The subtree's height changes from |
293 h+3 to h+2|h+3. */ | 293 h+3 to h+2|h+3. */ |
294 - noderight->balance - 1 | 294 - noderight->balance - 1 |
295 : /* noderight's height had been incremented from | 295 : /* noderight's height had been incremented from |
296 h+1 to h+2. The subtree's height changes from | 296 h+1 to h+2. The subtree's height changes from |
297 h+2 to h+2|h+3. */ | 297 h+2 to h+2|h+3. */ |
298 - noderight->balance); | 298 - noderight->balance); |
299 } | 299 } |
300 else | 300 else |
301 { | 301 { |
302 /* | 302 /* |
303 * h+2 | 303 * h+2 |
304 / \ / \ | 304 / \ / \ |
305 h h+2 --> h+1 h+1 | 305 h h+2 --> h+1 h+1 |
306 / \ / \ / \ | 306 / \ / \ / \ |
307 h+1 h h L R h | 307 h+1 h h L R h |
308 / \ | 308 / \ |
309 L R | 309 L R |
310 | 310 |
311 */ | 311 */ |
312 gl_list_node_t L = node->right = noderightleft->left; | 312 gl_list_node_t L = node->right = noderightleft->left; |
313 gl_list_node_t R = noderight->left = noderightleft->right; | 313 gl_list_node_t R = noderight->left = noderightleft->right; |
314 noderightleft->left = node; | 314 noderightleft->left = node; |
315 noderightleft->right = noderight; | 315 noderightleft->right = noderight; |
316 | 316 |
317 noderightleft->parent = node->parent; | 317 noderightleft->parent = node->parent; |
318 if (L != NULL) | 318 if (L != NULL) |
319 L->parent = node; | 319 L->parent = node; |
320 if (R != NULL) | 320 if (R != NULL) |
321 R->parent = noderight; | 321 R->parent = noderight; |
322 node->parent = noderightleft; | 322 node->parent = noderightleft; |
323 noderight->parent = noderightleft; | 323 noderight->parent = noderightleft; |
324 | 324 |
325 node->balance = (noderightleft->balance > 0 ? -1 : 0); | 325 node->balance = (noderightleft->balance > 0 ? -1 : 0); |
326 noderight->balance = (noderightleft->balance < 0 ? 1 : 0); | 326 noderight->balance = (noderightleft->balance < 0 ? 1 : 0); |
327 noderightleft->balance = 0; | 327 noderightleft->balance = 0; |
328 | 328 |
329 node->branch_size = | 329 node->branch_size = |
330 (node->left != NULL ? node->left->branch_size : 0) | 330 (node->left != NULL ? node->left->branch_size : 0) |
331 + 1 + (node->right != NULL ? node->right->branch_size : 0); | 331 + 1 + (node->right != NULL ? node->right->branch_size : 0); |
332 noderight->branch_size = | 332 noderight->branch_size = |
333 (noderight->left != NULL ? noderight->left->branch_size : 0) | 333 (noderight->left != NULL ? noderight->left->branch_size : 0) |
334 + 1 + (noderight->right != NULL ? noderight->right->branch_size : 0); | 334 + 1 + (noderight->right != NULL ? noderight->right->branch_size : 0); |
335 noderightleft->branch_size = | 335 noderightleft->branch_size = |
336 node->branch_size + 1 + noderight->branch_size; | 336 node->branch_size + 1 + noderight->branch_size; |
337 | 337 |
338 *nodep = noderightleft; | 338 *nodep = noderightleft; |
339 height_diff = (height_diff < 0 | 339 height_diff = (height_diff < 0 |
340 ? /* nodeleft's height had been decremented from | 340 ? /* nodeleft's height had been decremented from |
341 h+1 to h. The subtree's height changes from | 341 h+1 to h. The subtree's height changes from |
342 h+3 to h+2. */ | 342 h+3 to h+2. */ |
343 -1 | 343 -1 |
344 : /* noderight's height had been incremented from | 344 : /* noderight's height had been incremented from |
345 h+1 to h+2. The subtree's height changes from | 345 h+1 to h+2. The subtree's height changes from |
346 h+2 to h+2. */ | 346 h+2 to h+2. */ |
347 0); | 347 0); |
348 } | 348 } |
349 } | 349 } |
350 node = *nodep; | 350 node = *nodep; |
351 } | 351 } |
352 else | 352 else |
353 { | 353 { |
354 /* No rotation needed. Only propagation of the height change to the | 354 /* No rotation needed. Only propagation of the height change to the |
355 next higher level. */ | 355 next higher level. */ |
356 if (height_diff < 0) | 356 if (height_diff < 0) |
357 height_diff = (previous_balance == 0 ? 0 : -1); | 357 height_diff = (previous_balance == 0 ? 0 : -1); |
358 else | 358 else |
359 height_diff = (node->balance == 0 ? 0 : 1); | 359 height_diff = (node->balance == 0 ? 0 : 1); |
360 } | 360 } |
361 | 361 |
362 if (height_diff == 0) | 362 if (height_diff == 0) |
363 break; | 363 break; |
364 | 364 |
365 parent = node->parent; | 365 parent = node->parent; |
366 if (parent == NULL) | 366 if (parent == NULL) |
367 break; | 367 break; |
368 } | 368 } |
369 } | 369 } |
370 | 370 |
371 static gl_list_node_t | 371 static gl_list_node_t |
372 gl_tree_add_first (gl_list_t list, const void *elt) | 372 gl_tree_add_first (gl_list_t list, const void *elt) |
395 else | 395 else |
396 { | 396 { |
397 gl_list_node_t node; | 397 gl_list_node_t node; |
398 | 398 |
399 for (node = list->root; node->left != NULL; ) | 399 for (node = list->root; node->left != NULL; ) |
400 node = node->left; | 400 node = node->left; |
401 | 401 |
402 node->left = new_node; | 402 node->left = new_node; |
403 new_node->parent = node; | 403 new_node->parent = node; |
404 node->balance--; | 404 node->balance--; |
405 | 405 |
406 /* Update branch_size fields of the parent nodes. */ | 406 /* Update branch_size fields of the parent nodes. */ |
407 { | 407 { |
408 gl_list_node_t p; | 408 gl_list_node_t p; |
409 | 409 |
410 for (p = node; p != NULL; p = p->parent) | 410 for (p = node; p != NULL; p = p->parent) |
411 p->branch_size++; | 411 p->branch_size++; |
412 } | 412 } |
413 | 413 |
414 /* Rebalance. */ | 414 /* Rebalance. */ |
415 if (node->right == NULL && node->parent != NULL) | 415 if (node->right == NULL && node->parent != NULL) |
416 rebalance (list, node, 1, node->parent); | 416 rebalance (list, node, 1, node->parent); |
417 } | 417 } |
418 | 418 |
419 #if WITH_HASHTABLE | 419 #if WITH_HASHTABLE |
420 /* Add node to the hash table. | 420 /* Add node to the hash table. |
421 Note that this is only possible _after_ the node has been added to the | 421 Note that this is only possible _after_ the node has been added to the |
454 else | 454 else |
455 { | 455 { |
456 gl_list_node_t node; | 456 gl_list_node_t node; |
457 | 457 |
458 for (node = list->root; node->right != NULL; ) | 458 for (node = list->root; node->right != NULL; ) |
459 node = node->right; | 459 node = node->right; |
460 | 460 |
461 node->right = new_node; | 461 node->right = new_node; |
462 new_node->parent = node; | 462 new_node->parent = node; |
463 node->balance++; | 463 node->balance++; |
464 | 464 |
465 /* Update branch_size fields of the parent nodes. */ | 465 /* Update branch_size fields of the parent nodes. */ |
466 { | 466 { |
467 gl_list_node_t p; | 467 gl_list_node_t p; |
468 | 468 |
469 for (p = node; p != NULL; p = p->parent) | 469 for (p = node; p != NULL; p = p->parent) |
470 p->branch_size++; | 470 p->branch_size++; |
471 } | 471 } |
472 | 472 |
473 /* Rebalance. */ | 473 /* Rebalance. */ |
474 if (node->left == NULL && node->parent != NULL) | 474 if (node->left == NULL && node->parent != NULL) |
475 rebalance (list, node, 1, node->parent); | 475 rebalance (list, node, 1, node->parent); |
476 } | 476 } |
477 | 477 |
478 #if WITH_HASHTABLE | 478 #if WITH_HASHTABLE |
479 /* Add node to the hash table. | 479 /* Add node to the hash table. |
480 Note that this is only possible _after_ the node has been added to the | 480 Note that this is only possible _after_ the node has been added to the |
513 height_inc = (node->right == NULL); | 513 height_inc = (node->right == NULL); |
514 } | 514 } |
515 else | 515 else |
516 { | 516 { |
517 for (node = node->left; node->right != NULL; ) | 517 for (node = node->left; node->right != NULL; ) |
518 node = node->right; | 518 node = node->right; |
519 node->right = new_node; | 519 node->right = new_node; |
520 node->balance++; | 520 node->balance++; |
521 height_inc = (node->left == NULL); | 521 height_inc = (node->left == NULL); |
522 } | 522 } |
523 new_node->parent = node; | 523 new_node->parent = node; |
572 height_inc = (node->left == NULL); | 572 height_inc = (node->left == NULL); |
573 } | 573 } |
574 else | 574 else |
575 { | 575 { |
576 for (node = node->right; node->left != NULL; ) | 576 for (node = node->right; node->left != NULL; ) |
577 node = node->left; | 577 node = node->left; |
578 node->left = new_node; | 578 node->left = new_node; |
579 node->balance--; | 579 node->balance--; |
580 height_inc = (node->right == NULL); | 580 height_inc = (node->right == NULL); |
581 } | 581 } |
582 new_node->parent = node; | 582 new_node->parent = node; |
622 { | 622 { |
623 /* Replace node with node->right. */ | 623 /* Replace node with node->right. */ |
624 gl_list_node_t child = node->right; | 624 gl_list_node_t child = node->right; |
625 | 625 |
626 if (child != NULL) | 626 if (child != NULL) |
627 child->parent = parent; | 627 child->parent = parent; |
628 if (parent == NULL) | 628 if (parent == NULL) |
629 list->root = child; | 629 list->root = child; |
630 else | 630 else |
631 { | 631 { |
632 if (parent->left == node) | 632 if (parent->left == node) |
633 parent->left = child; | 633 parent->left = child; |
634 else /* parent->right == node */ | 634 else /* parent->right == node */ |
635 parent->right = child; | 635 parent->right = child; |
636 | 636 |
637 /* Update branch_size fields of the parent nodes. */ | 637 /* Update branch_size fields of the parent nodes. */ |
638 { | 638 { |
639 gl_list_node_t p; | 639 gl_list_node_t p; |
640 | 640 |
641 for (p = parent; p != NULL; p = p->parent) | 641 for (p = parent; p != NULL; p = p->parent) |
642 p->branch_size--; | 642 p->branch_size--; |
643 } | 643 } |
644 | 644 |
645 rebalance (list, child, -1, parent); | 645 rebalance (list, child, -1, parent); |
646 } | 646 } |
647 } | 647 } |
648 else if (node->right == NULL) | 648 else if (node->right == NULL) |
649 { | 649 { |
650 /* It is not absolutely necessary to treat this case. But the more | 650 /* It is not absolutely necessary to treat this case. But the more |
651 general case below is more complicated, hence slower. */ | 651 general case below is more complicated, hence slower. */ |
652 /* Replace node with node->left. */ | 652 /* Replace node with node->left. */ |
653 gl_list_node_t child = node->left; | 653 gl_list_node_t child = node->left; |
654 | 654 |
655 child->parent = parent; | 655 child->parent = parent; |
656 if (parent == NULL) | 656 if (parent == NULL) |
657 list->root = child; | 657 list->root = child; |
658 else | 658 else |
659 { | 659 { |
660 if (parent->left == node) | 660 if (parent->left == node) |
661 parent->left = child; | 661 parent->left = child; |
662 else /* parent->right == node */ | 662 else /* parent->right == node */ |
663 parent->right = child; | 663 parent->right = child; |
664 | 664 |
665 /* Update branch_size fields of the parent nodes. */ | 665 /* Update branch_size fields of the parent nodes. */ |
666 { | 666 { |
667 gl_list_node_t p; | 667 gl_list_node_t p; |
668 | 668 |
669 for (p = parent; p != NULL; p = p->parent) | 669 for (p = parent; p != NULL; p = p->parent) |
670 p->branch_size--; | 670 p->branch_size--; |
671 } | 671 } |
672 | 672 |
673 rebalance (list, child, -1, parent); | 673 rebalance (list, child, -1, parent); |
674 } | 674 } |
675 } | 675 } |
676 else | 676 else |
677 { | 677 { |
678 /* Replace node with the rightmost element of the node->left subtree. */ | 678 /* Replace node with the rightmost element of the node->left subtree. */ |
679 gl_list_node_t subst; | 679 gl_list_node_t subst; |
680 gl_list_node_t subst_parent; | 680 gl_list_node_t subst_parent; |
681 gl_list_node_t child; | 681 gl_list_node_t child; |
682 | 682 |
683 for (subst = node->left; subst->right != NULL; ) | 683 for (subst = node->left; subst->right != NULL; ) |
684 subst = subst->right; | 684 subst = subst->right; |
685 | 685 |
686 subst_parent = subst->parent; | 686 subst_parent = subst->parent; |
687 | 687 |
688 child = subst->left; | 688 child = subst->left; |
689 | 689 |
690 /* The case subst_parent == node is special: If we do nothing special, | 690 /* The case subst_parent == node is special: If we do nothing special, |
691 we get confusion about node->left, subst->left and child->parent. | 691 we get confusion about node->left, subst->left and child->parent. |
692 subst_parent == node | 692 subst_parent == node |
693 <==> The 'for' loop above terminated immediately. | 693 <==> The 'for' loop above terminated immediately. |
694 <==> subst == subst_parent->left | 694 <==> subst == subst_parent->left |
695 [otherwise subst == subst_parent->right] | 695 [otherwise subst == subst_parent->right] |
696 In this case, we would need to first set | 696 In this case, we would need to first set |
697 child->parent = node; node->left = child; | 697 child->parent = node; node->left = child; |
698 and later - when we copy subst into node's position - again | 698 and later - when we copy subst into node's position - again |
699 child->parent = subst; subst->left = child; | 699 child->parent = subst; subst->left = child; |
700 Altogether a no-op. */ | 700 Altogether a no-op. */ |
701 if (subst_parent != node) | 701 if (subst_parent != node) |
702 { | 702 { |
703 if (child != NULL) | 703 if (child != NULL) |
704 child->parent = subst_parent; | 704 child->parent = subst_parent; |
705 subst_parent->right = child; | 705 subst_parent->right = child; |
706 } | 706 } |
707 | 707 |
708 /* Update branch_size fields of the parent nodes. */ | 708 /* Update branch_size fields of the parent nodes. */ |
709 { | 709 { |
710 gl_list_node_t p; | 710 gl_list_node_t p; |
711 | 711 |
712 for (p = subst_parent; p != NULL; p = p->parent) | 712 for (p = subst_parent; p != NULL; p = p->parent) |
713 p->branch_size--; | 713 p->branch_size--; |
714 } | 714 } |
715 | 715 |
716 /* Copy subst into node's position. | 716 /* Copy subst into node's position. |
717 (This is safer than to copy subst's value into node, keep node in | 717 (This is safer than to copy subst's value into node, keep node in |
718 place, and free subst.) */ | 718 place, and free subst.) */ |
719 if (subst_parent != node) | 719 if (subst_parent != node) |
720 { | 720 { |
721 subst->left = node->left; | 721 subst->left = node->left; |
722 subst->left->parent = subst; | 722 subst->left->parent = subst; |
723 } | 723 } |
724 subst->right = node->right; | 724 subst->right = node->right; |
725 subst->right->parent = subst; | 725 subst->right->parent = subst; |
726 subst->balance = node->balance; | 726 subst->balance = node->balance; |
727 subst->branch_size = node->branch_size; | 727 subst->branch_size = node->branch_size; |
728 subst->parent = parent; | 728 subst->parent = parent; |
729 if (parent == NULL) | 729 if (parent == NULL) |
730 list->root = subst; | 730 list->root = subst; |
731 else if (parent->left == node) | 731 else if (parent->left == node) |
732 parent->left = subst; | 732 parent->left = subst; |
733 else /* parent->right == node */ | 733 else /* parent->right == node */ |
734 parent->right = subst; | 734 parent->right = subst; |
735 | 735 |
736 /* Rebalancing starts at child's parent, that is subst_parent - | 736 /* Rebalancing starts at child's parent, that is subst_parent - |
737 except when subst_parent == node. In this case, we need to use | 737 except when subst_parent == node. In this case, we need to use |
738 its replacement, subst. */ | 738 its replacement, subst. */ |
739 rebalance (list, child, -1, subst_parent != node ? subst_parent : subst); | 739 rebalance (list, child, -1, subst_parent != node ? subst_parent : subst); |
740 } | 740 } |
741 | 741 |
742 if (list->base.dispose_fn != NULL) | 742 if (list->base.dispose_fn != NULL) |
743 list->base.dispose_fn (node->value); | 743 list->base.dispose_fn (node->value); |