Rev 2501 | Rev 2504 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 2501 | Rev 2503 | ||
|---|---|---|---|
| Line 105... | Line 105... | ||
| 105 | p = p->lft; |
105 | p = p->lft; |
| 106 | 106 | ||
| 107 | return p; |
107 | return p; |
| 108 | } |
108 | } |
| 109 | 109 | ||
| - | 110 | #define REBALANCE_INSERT_XX(DIR1, DIR2) \ |
|
| - | 111 | top->DIR1 = par->DIR2; \ |
|
| - | 112 | if (top->DIR1 != NULL) \ |
|
| - | 113 | top->DIR1->par = top; \ |
|
| - | 114 | par->par = top->par; \ |
|
| - | 115 | top->par = par; \ |
|
| - | 116 | par->DIR2 = top; \ |
|
| - | 117 | par->balance = 0; \ |
|
| - | 118 | top->balance = 0; \ |
|
| - | 119 | *dpc = par; |
|
| - | 120 | ||
| - | 121 | #define REBALANCE_INSERT_LL() REBALANCE_INSERT_XX(lft, rgt) |
|
| - | 122 | #define REBALANCE_INSERT_RR() REBALANCE_INSERT_XX(rgt, lft) |
|
| - | 123 | ||
| - | 124 | #define REBALANCE_INSERT_XY(DIR1, DIR2, SGN) \ |
|
| - | 125 | gpa = par->DIR2; \ |
|
| - | 126 | par->DIR2 = gpa->DIR1; \ |
|
| - | 127 | if (gpa->DIR1 != NULL) \ |
|
| - | 128 | gpa->DIR1->par = par; \ |
|
| - | 129 | gpa->DIR1 = par; \ |
|
| - | 130 | par->par = gpa; \ |
|
| - | 131 | top->DIR1 = gpa->DIR2; \ |
|
| - | 132 | if (gpa->DIR2 != NULL) \ |
|
| - | 133 | gpa->DIR2->par = top; \ |
|
| - | 134 | gpa->DIR2 = top; \ |
|
| - | 135 | gpa->par = top->par; \ |
|
| - | 136 | top->par = gpa; \ |
|
| - | 137 | \ |
|
| - | 138 | if (gpa->balance == -1 * SGN) { \ |
|
| - | 139 | par->balance = 0; \ |
|
| - | 140 | top->balance = 1 * SGN; \ |
|
| - | 141 | } else if (gpa->balance == 0) { \ |
|
| - | 142 | par->balance = 0; \ |
|
| - | 143 | top->balance = 0; \ |
|
| - | 144 | } else { \ |
|
| - | 145 | par->balance = -1 * SGN; \ |
|
| - | 146 | top->balance = 0; \ |
|
| - | 147 | } \ |
|
| - | 148 | gpa->balance = 0; \ |
|
| - | 149 | *dpc = gpa; |
|
| - | 150 | ||
| - | 151 | #define REBALANCE_INSERT_LR() REBALANCE_INSERT_XY(lft, rgt, 1) |
|
| - | 152 | #define REBALANCE_INSERT_RL() REBALANCE_INSERT_XY(rgt, lft, -1) |
|
| - | 153 | ||
| 110 | /** Insert new node into AVL tree. |
154 | /** Insert new node into AVL tree. |
| 111 | * |
155 | * |
| 112 | * @param t AVL tree. |
156 | * @param t AVL tree. |
| 113 | * @param newnode New node to be inserted. |
157 | * @param newnode New node to be inserted. |
| 114 | */ |
158 | */ |
| Line 143... | Line 187... | ||
| 143 | gpa = par; |
187 | gpa = par; |
| 144 | dpc = par->key > key ? &par->lft: &par->rgt; |
188 | dpc = par->key > key ? &par->lft: &par->rgt; |
| 145 | } |
189 | } |
| 146 | 190 | ||
| 147 | /* |
191 | /* |
| 148 | * Initialize new node. |
192 | * Initialize the new node. |
| 149 | */ |
193 | */ |
| 150 | newnode->key = key; |
194 | newnode->key = key; |
| 151 | newnode->lft = NULL; |
195 | newnode->lft = NULL; |
| 152 | newnode->rgt = NULL; |
196 | newnode->rgt = NULL; |
| 153 | newnode->par = gpa; |
197 | newnode->par = gpa; |
| Line 160... | Line 204... | ||
| 160 | *dpc = newnode; |
204 | *dpc = newnode; |
| 161 | return; |
205 | return; |
| 162 | } |
206 | } |
| 163 | 207 | ||
| 164 | /* |
208 | /* |
| 165 | * Insert new node into previously found leaf place. |
209 | * Insert the new node into the previously found leaf position. |
| 166 | */ |
210 | */ |
| 167 | *dpc = newnode; |
211 | *dpc = newnode; |
| 168 | 212 | ||
| 169 | /* |
213 | /* |
| 170 | * If the tree contains one node - end. |
214 | * If the tree contains one node - end. |
| Line 207... | Line 251... | ||
| 207 | par = top->lft; |
251 | par = top->lft; |
| 208 | if (par->balance == -1) { |
252 | if (par->balance == -1) { |
| 209 | /* |
253 | /* |
| 210 | * LL rotation. |
254 | * LL rotation. |
| 211 | */ |
255 | */ |
| 212 | top->lft = par->rgt; |
- | |
| 213 | if (top->lft != NULL) |
256 | REBALANCE_INSERT_LL(); |
| 214 | top->lft->par = top; |
- | |
| 215 | par->par = top->par; |
- | |
| 216 | top->par = par; |
- | |
| 217 | par->rgt = top; |
- | |
| 218 | par->balance = 0; |
- | |
| 219 | top->balance = 0; |
- | |
| 220 | *dpc = par; |
- | |
| 221 | } else { |
257 | } else { |
| 222 | /* |
258 | /* |
| 223 | * LR rotation. |
259 | * LR rotation. |
| 224 | */ |
260 | */ |
| 225 | ASSERT(par->balance == 1); |
261 | ASSERT(par->balance == 1); |
| 226 | 262 | ||
| 227 | gpa = par->rgt; |
- | |
| 228 | par->rgt = gpa->lft; |
- | |
| 229 | if (gpa->lft != NULL) |
- | |
| 230 | gpa->lft->par = par; |
263 | REBALANCE_INSERT_LR(); |
| 231 | gpa->lft = par; |
- | |
| 232 | par->par = gpa; |
- | |
| 233 | top->lft = gpa->rgt; |
- | |
| 234 | if (gpa->rgt != NULL) |
- | |
| 235 | gpa->rgt->par = top; |
- | |
| 236 | gpa->rgt = top; |
- | |
| 237 | gpa->par = top->par; |
- | |
| 238 | top->par = gpa; |
- | |
| 239 | - | ||
| 240 | if (gpa->balance == -1) { |
- | |
| 241 | par->balance = 0; |
- | |
| 242 | top->balance = 1; |
- | |
| 243 | } else if (gpa->balance == 0) { |
- | |
| 244 | par->balance = 0; |
- | |
| 245 | top->balance = 0; |
- | |
| 246 | } else { |
- | |
| 247 | par->balance = -1; |
- | |
| 248 | top->balance = 0; |
- | |
| 249 | } |
- | |
| 250 | gpa->balance = 0; |
- | |
| 251 | *dpc = gpa; |
- | |
| 252 | } |
264 | } |
| 253 | } else if (top->balance == 2) { |
265 | } else if (top->balance == 2) { |
| 254 | par = top->rgt; |
266 | par = top->rgt; |
| 255 | if (par->balance == 1) { |
267 | if (par->balance == 1) { |
| 256 | /* |
268 | /* |
| 257 | * RR rotation. |
269 | * RR rotation. |
| 258 | */ |
270 | */ |
| 259 | top->rgt = par->lft; |
- | |
| 260 | if (top->rgt != NULL) |
- | |
| 261 | top->rgt->par = top; |
271 | REBALANCE_INSERT_RR(); |
| 262 | par->par = top->par; |
- | |
| 263 | top->par = par; |
- | |
| 264 | par->lft = top; |
- | |
| 265 | par->balance = 0; |
- | |
| 266 | top->balance = 0; |
- | |
| 267 | *dpc = par; |
- | |
| 268 | } else { |
272 | } else { |
| 269 | /* |
273 | /* |
| 270 | * RL rotation. |
274 | * RL rotation. |
| 271 | */ |
275 | */ |
| 272 | ASSERT(par->balance == -1); |
276 | ASSERT(par->balance == -1); |
| 273 | 277 | ||
| 274 | gpa = par->lft; |
- | |
| 275 | par->lft = gpa->rgt; |
- | |
| 276 | if (gpa->rgt != NULL) |
- | |
| 277 | gpa->rgt->par = par; |
- | |
| 278 | gpa->rgt = par; |
- | |
| 279 | par->par = gpa; |
- | |
| 280 | top->rgt = gpa->lft; |
- | |
| 281 | if (gpa->lft != NULL) |
278 | REBALANCE_INSERT_RL(); |
| 282 | gpa->lft->par = top; |
- | |
| 283 | gpa->lft = top; |
- | |
| 284 | gpa->par = top->par; |
- | |
| 285 | top->par = gpa; |
- | |
| 286 | - | ||
| 287 | if (gpa->balance == 1) { |
- | |
| 288 | par->balance = 0; |
- | |
| 289 | top->balance = -1; |
- | |
| 290 | } else if (gpa->balance == 0) { |
- | |
| 291 | par->balance = 0; |
- | |
| 292 | top->balance = 0; |
- | |
| 293 | } else { |
- | |
| 294 | par->balance = 1; |
- | |
| 295 | top->balance = 0; |
- | |
| 296 | } |
- | |
| 297 | gpa->balance = 0; |
- | |
| 298 | *dpc = gpa; |
- | |
| 299 | } |
279 | } |
| 300 | } else { |
280 | } else { |
| 301 | /* |
281 | /* |
| 302 | * Balance is not broken, insertion is finised. |
282 | * Balance is not broken, insertion is finised. |
| 303 | */ |
283 | */ |
| Line 349... | Line 329... | ||
| 349 | } |
329 | } |
| 350 | } |
330 | } |
| 351 | return 1; |
331 | return 1; |
| 352 | } |
332 | } |
| 353 | 333 | ||
| 354 | #define REBALANCE(DIR1, DIR2, SIGN) \ |
334 | #define REBALANCE_DELETE(DIR1, DIR2, SIGN) \ |
| 355 | if (cur->balance == -1 * SIGN) { \ |
335 | if (cur->balance == -1 * SIGN) { \ |
| 356 | par->balance = 0; \ |
336 | par->balance = 0; \ |
| 357 | gpa->balance = 1 * SIGN; \ |
337 | gpa->balance = 1 * SIGN; \ |
| 358 | if (gpa->DIR1) \ |
338 | if (gpa->DIR1) \ |
| 359 | gpa->DIR1->par = gpa; \ |
339 | gpa->DIR1->par = gpa; \ |
| Line 372... | Line 352... | ||
| 372 | par->DIR2->par = par; \ |
352 | par->DIR2->par = par; \ |
| 373 | gpa->DIR1->par = gpa; \ |
353 | gpa->DIR1->par = gpa; \ |
| 374 | } \ |
354 | } \ |
| 375 | cur->balance = 0; |
355 | cur->balance = 0; |
| 376 | 356 | ||
| 377 | #define REBALANCE_LR() REBALANCE(lft, rgt, 1) |
357 | #define REBALANCE_DELETE_LR() REBALANCE_DELETE(lft, rgt, 1) |
| 378 | #define REBALANCE_RL() REBALANCE(rgt, lft, -1) |
358 | #define REBALANCE_DELETE_RL() REBALANCE_DELETE(rgt, lft, -1) |
| 379 | 359 | ||
| 380 | /** Delete a node from the AVL tree. |
360 | /** Delete a node from the AVL tree. |
| 381 | * |
361 | * |
| 382 | * Because multiple identical keys are allowed, the parent pointers are |
362 | * Because multiple identical keys are allowed, the parent pointers are |
| 383 | * essential during deletion. |
363 | * essential during deletion. |
| Line 513... | Line 493... | ||
| 513 | /* |
493 | /* |
| 514 | * Repair balances and paternity of |
494 | * Repair balances and paternity of |
| 515 | * children, depending on the balance |
495 | * children, depending on the balance |
| 516 | * factor of the grand child (cur). |
496 | * factor of the grand child (cur). |
| 517 | */ |
497 | */ |
| 518 | REBALANCE_RL(); |
498 | REBALANCE_DELETE_RL(); |
| 519 | 499 | ||
| 520 | /* |
500 | /* |
| 521 | * Repair paternity. |
501 | * Repair paternity. |
| 522 | */ |
502 | */ |
| 523 | cur->par = gpa->par; |
503 | cur->par = gpa->par; |
| Line 609... | Line 589... | ||
| 609 | /* |
589 | /* |
| 610 | * Repair balances and paternity of |
590 | * Repair balances and paternity of |
| 611 | * children, depending on the balance |
591 | * children, depending on the balance |
| 612 | * factor of the grand child (cur). |
592 | * factor of the grand child (cur). |
| 613 | */ |
593 | */ |
| 614 | REBALANCE_LR(); |
594 | REBALANCE_DELETE_LR(); |
| 615 | 595 | ||
| 616 | /* |
596 | /* |
| 617 | * Repair paternity. |
597 | * Repair paternity. |
| 618 | */ |
598 | */ |
| 619 | cur->par = gpa->par; |
599 | cur->par = gpa->par; |