5 * Copyright (c) 2010-2013 by Manfred Moitzi
15 #define KEY(node) (node->key)
16 #define VALUE(node) (node->value)
17 #define LEFT_NODE(node) (node->link[LEFT])
18 #define RIGHT_NODE(node) (node->link[RIGHT])
19 #define LINK(node, dir) (node->link[dir])
20 #define XDATA(node) (node->xdata)
21 #define RED(node) (node->xdata)
22 #define BALANCE(node) (node->xdata)
25 ct_new_node(PyObject
*key
, PyObject
*value
, int xdata
)
27 node_t
*new_node
= PyMem_Malloc(sizeof(node_t
));
28 if (new_node
!= NULL
) {
31 VALUE(new_node
) = value
;
33 LEFT_NODE(new_node
) = NULL
;
34 RIGHT_NODE(new_node
) = NULL
;
35 XDATA(new_node
) = xdata
;
41 ct_delete_node(node_t
*node
)
44 Py_XDECREF(KEY(node
));
45 Py_XDECREF(VALUE(node
));
46 LEFT_NODE(node
) = NULL
;
47 RIGHT_NODE(node
) = NULL
;
53 ct_delete_tree(node_t
*root
)
57 if (LEFT_NODE(root
) != NULL
) {
58 ct_delete_tree(LEFT_NODE(root
));
60 if (RIGHT_NODE(root
) != NULL
) {
61 ct_delete_tree(RIGHT_NODE(root
));
67 ct_swap_data(node_t
*node1
, node_t
*node2
)
71 KEY(node1
) = KEY(node2
);
74 VALUE(node1
) = VALUE(node2
);
79 ct_compare(PyObject
*key1
, PyObject
*key2
)
83 res
= PyObject_RichCompareBool(key1
, key2
, Py_LT
);
87 PyErr_SetString(PyExc_TypeError
, "invalid type for key");
93 -1 means error, if error, it should happend at the first compare
95 return PyObject_RichCompareBool(key1
, key2
, Py_GT
);
99 ct_find_node(node_t
*root
, PyObject
*key
)
102 while (root
!= NULL
) {
103 res
= ct_compare(key
, KEY(root
));
104 if (res
== 0) /* key found */
107 root
= LINK(root
, (res
> 0));
110 return NULL
; /* key not found */
114 ct_get_item(node_t
*root
, PyObject
*key
)
119 node
= ct_find_node(root
, key
);
121 tuple
= PyTuple_New(2);
122 PyTuple_SET_ITEM(tuple
, 0, KEY(node
));
123 PyTuple_SET_ITEM(tuple
, 1, VALUE(node
));
130 ct_max_node(node_t
*root
)
131 /* get node with largest key */
135 while (RIGHT_NODE(root
) != NULL
)
136 root
= RIGHT_NODE(root
);
141 ct_min_node(node_t
*root
)
142 // get node with smallest key
146 while (LEFT_NODE(root
) != NULL
)
147 root
= LEFT_NODE(root
);
152 ct_bintree_remove(node_t
**rootaddr
, PyObject
*key
)
153 /* attention: rootaddr is the address of the root pointer */
155 node_t
*node
, *parent
, *replacement
;
156 int direction
, cmp_res
, down_dir
;
161 return 0; /* root is NULL */
166 cmp_res
= ct_compare(key
, KEY(node
));
167 if (cmp_res
== 0) /* key found, remove node */
169 if ((LEFT_NODE(node
) != NULL
) && (RIGHT_NODE(node
) != NULL
)) {
170 /* find replacement node: smallest key in right-subtree */
173 replacement
= RIGHT_NODE(node
);
174 while (LEFT_NODE(replacement
) != NULL
) {
175 parent
= replacement
;
177 replacement
= LEFT_NODE(replacement
);
179 LINK(parent
, direction
) = RIGHT_NODE(replacement
);
181 ct_swap_data(node
, replacement
);
182 node
= replacement
; /* delete replacement node */
185 down_dir
= (LEFT_NODE(node
) == NULL
) ? RIGHT
: LEFT
;
186 if (parent
== NULL
) /* root */
188 *rootaddr
= LINK(node
, down_dir
);
191 LINK(parent
, direction
) = LINK(node
, down_dir
);
194 ct_delete_node(node
);
195 return 1; /* remove was success full */
198 direction
= (cmp_res
< 0) ? LEFT
: RIGHT
;
200 node
= LINK(node
, direction
);
202 return 0; /* error key not found */
208 ct_bintree_insert(node_t
**rootaddr
, PyObject
*key
, PyObject
*value
)
209 /* attention: rootaddr is the address of the root pointer */
211 node_t
*parent
, *node
;
215 node
= ct_new_node(key
, value
, 0); /* new node is also the root */
217 return -1; /* got no memory */
225 node
= ct_new_node(key
, value
, 0);
227 return -1; /* get no memory */
228 LINK(parent
, direction
) = node
;
231 cval
= ct_compare(key
, KEY(node
));
233 /* key exists, replace value object */
234 Py_XDECREF(VALUE(node
)); /* release old value object */
235 VALUE(node
) = value
; /* set new value object */
236 Py_INCREF(value
); /* take new value object */
241 direction
= (cval
< 0) ? LEFT
: RIGHT
;
242 node
= LINK(node
, direction
);
250 is_red (node_t
*node
)
252 return (node
!= NULL
) && (RED(node
) == 1);
255 #define rb_new_node(key, value) ct_new_node(key, value, 1)
258 rb_single(node_t
*root
, int dir
)
260 node_t
*save
= root
->link
[!dir
];
262 root
->link
[!dir
] = save
->link
[dir
];
263 save
->link
[dir
] = root
;
271 rb_double(node_t
*root
, int dir
)
273 root
->link
[!dir
] = rb_single(root
->link
[!dir
], !dir
);
274 return rb_single(root
, dir
);
277 #define rb_new_node(key, value) ct_new_node(key, value, 1)
280 rb_insert(node_t
**rootaddr
, PyObject
*key
, PyObject
*value
)
282 node_t
*root
= *rootaddr
;
286 We have an empty tree; attach the
287 new node directly to the root
289 root
= rb_new_node(key
, value
);
291 return -1; // got no memory
294 node_t head
; /* False tree root */
295 node_t
*g
, *t
; /* Grandparent & parent */
296 node_t
*p
, *q
; /* Iterator & parent */
301 /* Set up our helpers */
305 RIGHT_NODE(t
) = root
;
309 /* Search down the tree for a place to insert */
313 /* Insert a new node at the first null link */
314 q
= rb_new_node(key
, value
);
318 return -1; // get no memory
320 else if (is_red(q
->link
[0]) && is_red(q
->link
[1])) {
321 /* Simple red violation: color flip */
327 if (is_red(q
) && is_red(p
)) {
328 /* Hard red violation: rotations necessary */
329 int dir2
= (t
->link
[1] == g
);
331 if (q
== p
->link
[last
])
332 t
->link
[dir2
] = rb_single(g
, !last
);
334 t
->link
[dir2
] = rb_double(g
, !last
);
337 /* Stop working if we inserted a new node. */
341 cmp_res
= ct_compare(KEY(q
), key
);
342 if (cmp_res
== 0) { /* key exists? */
343 Py_XDECREF(VALUE(q
)); /* release old value object */
344 VALUE(q
) = value
; /* set new value object */
345 Py_INCREF(value
); /* take new value object */
351 /* Move the helpers down */
359 /* Update the root (it may be different) */
363 /* Make the root black for simplified logic */
370 rb_remove(node_t
**rootaddr
, PyObject
*key
)
372 node_t
*root
= *rootaddr
;
374 node_t head
= { { NULL
} }; /* False tree root */
375 node_t
*q
, *p
, *g
; /* Helpers */
376 node_t
*f
= NULL
; /* Found item */
382 /* Set up our helpers */
385 RIGHT_NODE(q
) = root
;
388 Search and push a red node down
389 to fix red violations as we go
391 while (q
->link
[dir
] != NULL
) {
395 /* Move the helpers down */
399 cmp_res
= ct_compare(KEY(q
), key
);
404 Save the node with matching data and keep
405 going; we'll do removal tasks at the end
410 /* Push the red node down with rotations and color flips */
411 if (!is_red(q
) && !is_red(q
->link
[dir
])) {
412 if (is_red(q
->link
[!dir
]))
413 p
= p
->link
[last
] = rb_single(q
, dir
);
414 else if (!is_red(q
->link
[!dir
])) {
415 node_t
*s
= p
->link
[!last
];
418 if (!is_red(s
->link
[!last
]) &&
419 !is_red(s
->link
[last
])) {
426 int dir2
= g
->link
[1] == p
;
428 if (is_red(s
->link
[last
]))
429 g
->link
[dir2
] = rb_double(p
, last
);
430 else if (is_red(s
->link
[!last
]))
431 g
->link
[dir2
] = rb_single(p
, last
);
433 /* Ensure correct coloring */
434 RED(q
) = RED(g
->link
[dir2
]) = 1;
435 RED(g
->link
[dir2
]->link
[0]) = 0;
436 RED(g
->link
[dir2
]->link
[1]) = 0;
443 /* Replace and remove the saved node */
446 p
->link
[p
->link
[1] == q
] = q
->link
[q
->link
[0] == NULL
];
450 /* Update the root (it may be different) */
453 /* Make the root black for simplified logic */
460 #define avl_new_node(key, value) ct_new_node(key, value, 0)
461 #define height(p) ((p) == NULL ? -1 : (p)->xdata)
462 #define avl_max(a, b) ((a) > (b) ? (a) : (b))
465 avl_single(node_t
*root
, int dir
)
467 node_t
*save
= root
->link
[!dir
];
471 root
->link
[!dir
] = save
->link
[dir
];
472 save
->link
[dir
] = root
;
474 /* Update balance factors */
475 rlh
= height(root
->link
[0]);
476 rrh
= height(root
->link
[1]);
477 slh
= height(save
->link
[!dir
]);
479 BALANCE(root
) = avl_max(rlh
, rrh
) + 1;
480 BALANCE(save
) = avl_max(slh
, BALANCE(root
)) + 1;
486 avl_double(node_t
*root
, int dir
)
488 root
->link
[!dir
] = avl_single(root
->link
[!dir
], !dir
);
489 return avl_single(root
, dir
);
493 avl_insert(node_t
**rootaddr
, PyObject
*key
, PyObject
*value
)
495 node_t
*root
= *rootaddr
;
498 root
= avl_new_node(key
, value
);
500 return -1; // got no memory
504 int upd
[32], top
= 0;
509 /* Search for an empty link, save the path */
511 /* Push direction and node onto stack */
512 cmp_res
= ct_compare(KEY(it
), key
);
514 Py_XDECREF(VALUE(it
)); // release old value object
515 VALUE(it
) = value
; // set new value object
516 Py_INCREF(value
); // take new value object
519 // upd[top] = it->data < data;
520 upd
[top
] = (cmp_res
< 0);
523 if (it
->link
[upd
[top
- 1]] == NULL
)
525 it
= it
->link
[upd
[top
- 1]];
528 /* Insert a new node at the bottom of the tree */
529 it
->link
[upd
[top
- 1]] = avl_new_node(key
, value
);
530 if (it
->link
[upd
[top
- 1]] == NULL
)
531 return -1; // got no memory
533 /* Walk back up the search path */
534 while (--top
>= 0 && !done
) {
535 // int dir = (cmp_res < 0);
538 cmp_res
= ct_compare(KEY(up
[top
]), key
);
540 lh
= height(up
[top
]->link
[upd
[top
]]);
541 rh
= height(up
[top
]->link
[!upd
[top
]]);
543 /* Terminate or rebalance as necessary */
547 node_t
*a
= up
[top
]->link
[upd
[top
]]->link
[upd
[top
]];
548 node_t
*b
= up
[top
]->link
[upd
[top
]]->link
[!upd
[top
]];
550 if (height( a
) >= height( b
))
551 up
[top
] = avl_single(up
[top
], !upd
[top
]);
553 up
[top
] = avl_double(up
[top
], !upd
[top
]);
557 up
[top
- 1]->link
[upd
[top
- 1]] = up
[top
];
562 /* Update balance factors */
563 lh
= height(up
[top
]->link
[upd
[top
]]);
564 rh
= height(up
[top
]->link
[!upd
[top
]]);
565 max
= avl_max(lh
, rh
);
566 BALANCE(up
[top
]) = max
+ 1;
574 avl_remove(node_t
**rootaddr
, PyObject
*key
)
576 node_t
*root
= *rootaddr
;
581 int upd
[32], top
= 0;
585 /* Terminate if not found */
588 cmp_res
= ct_compare(KEY(it
), key
);
592 /* Push direction and node onto stack */
593 upd
[top
] = (cmp_res
< 0);
595 it
= it
->link
[upd
[top
- 1]];
598 /* Remove the node */
599 if (it
->link
[0] == NULL
||
600 it
->link
[1] == NULL
) {
601 /* Which child is not null? */
602 int dir
= it
->link
[0] == NULL
;
606 up
[top
- 1]->link
[upd
[top
- 1]] = it
->link
[dir
];
608 root
= it
->link
[dir
];
613 /* Find the inorder successor */
614 node_t
*heir
= it
->link
[1];
620 while ( heir
->link
[0] != NULL
) {
623 heir
= heir
->link
[0];
626 ct_swap_data(it
, heir
);
627 /* Unlink successor and fix parent */
628 up
[top
- 1]->link
[up
[top
- 1] == it
] = heir
->link
[1];
629 ct_delete_node(heir
);
632 /* Walk back up the search path */
634 int lh
= height(up
[top
]->link
[upd
[top
]]);
635 int rh
= height(up
[top
]->link
[!upd
[top
]]);
636 int max
= avl_max(lh
, rh
);
638 /* Update balance factors */
639 BALANCE(up
[top
]) = max
+ 1;
641 /* Terminate or rebalance as necessary */
645 node_t
*a
= up
[top
]->link
[!upd
[top
]]->link
[upd
[top
]];
646 node_t
*b
= up
[top
]->link
[!upd
[top
]]->link
[!upd
[top
]];
648 if (height(a
) <= height(b
))
649 up
[top
] = avl_single(up
[top
], upd
[top
]);
651 up
[top
] = avl_double(up
[top
], upd
[top
]);
655 up
[top
- 1]->link
[upd
[top
- 1]] = up
[top
];
666 ct_succ_node(node_t
*root
, PyObject
*key
)
672 while (node
!= NULL
) {
673 cval
= ct_compare(key
, KEY(node
));
677 if ((succ
== NULL
) ||
678 (ct_compare(KEY(node
), KEY(succ
)) < 0))
680 node
= LEFT_NODE(node
);
682 node
= RIGHT_NODE(node
);
686 /* found node of key */
687 if (RIGHT_NODE(node
) != NULL
) {
688 /* find smallest node of right subtree */
689 node
= RIGHT_NODE(node
);
690 while (LEFT_NODE(node
) != NULL
)
691 node
= LEFT_NODE(node
);
694 else if (ct_compare(KEY(node
), KEY(succ
)) < 0)
701 ct_prev_node(node_t
*root
, PyObject
*key
)
707 while (node
!= NULL
) {
708 cval
= ct_compare(key
, KEY(node
));
712 node
= LEFT_NODE(node
);
714 if ((prev
== NULL
) || (ct_compare(KEY(node
), KEY(prev
)) > 0))
716 node
= RIGHT_NODE(node
);
719 if (node
== NULL
) /* stay at dead end (None) */
721 /* found node of key */
722 if (LEFT_NODE(node
) != NULL
) {
723 /* find biggest node of left subtree */
724 node
= LEFT_NODE(node
);
725 while (RIGHT_NODE(node
) != NULL
)
726 node
= RIGHT_NODE(node
);
729 else if (ct_compare(KEY(node
), KEY(prev
)) > 0)
736 ct_floor_node(node_t
*root
, PyObject
*key
)
742 while (node
!= NULL
) {
743 cval
= ct_compare(key
, KEY(node
));
747 node
= LEFT_NODE(node
);
749 if ((prev
== NULL
) || (ct_compare(KEY(node
), KEY(prev
)) > 0))
751 node
= RIGHT_NODE(node
);
758 ct_ceiling_node(node_t
*root
, PyObject
*key
)
764 while (node
!= NULL
) {
765 cval
= ct_compare(key
, KEY(node
));
769 if ((succ
== NULL
) ||
770 (ct_compare(KEY(node
), KEY(succ
)) < 0))
772 node
= LEFT_NODE(node
);
774 node
= RIGHT_NODE(node
);
780 ct_index_of(node_t
*root
, PyObject
*key
)
782 get index of item <key>, returns -1 if key not found.
789 stack
= stack_init(32);
792 if ((LEFT_NODE(node
) != NULL
) && go_down
) {
793 stack_push(stack
, node
);
794 node
= LEFT_NODE(node
);
797 if (ct_compare(KEY(node
), key
) == 0) {
802 if (RIGHT_NODE(node
) != NULL
) {
803 node
= RIGHT_NODE(node
);
807 if (stack_is_empty(stack
)) {
811 node
= stack_pop(stack
);
819 ct_node_at(node_t
*root
, int index
)
822 root -- root node of tree
823 index -- index of wanted node
825 return NULL if index out of range
832 if (index
< 0) return NULL
;
834 stack
= stack_init(32);
837 if ((LEFT_NODE(node
) != NULL
) && go_down
) {
838 stack_push(stack
, node
);
839 node
= LEFT_NODE(node
);
842 if (counter
== index
) {
843 /* reached wanted index */
848 if (RIGHT_NODE(node
) != NULL
) {
849 node
= RIGHT_NODE(node
);
853 if (stack_is_empty(stack
)) { /* index out of range */
857 node
= stack_pop(stack
);