unicstl/datastruct/rbtree.c
2024-06-18 10:08:40 +08:00

1187 lines
22 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "rbtree.h"
#include "stack.h"
#include "queue.h"
#if RBTREE == 1
// ----------------------------------------
// rbtree ÊôÐÔ¸´ÓÃ
#define RBT_COLOR(x) ((x)->color)
#define RBT_COLOR_INIT(x) (RBT_COLOR(x) = 0)
// color <- bit[0]
#define RBT_COLOR_MASK (0x01)
#define RBT_BALCK (0x01)
#define BRT_RED (0x00)
#define RBT_SET_RED(x) (RBT_COLOR(x) &= ~RBT_BALCK)
#define RBT_SET_BLACK(x) (RBT_COLOR(x) |= RBT_BALCK)
#define RBT_IS_BLACK(x) (((RBT_COLOR(x) & RBT_BALCK) == RBT_BALCK)?true:false)
#define RBT_IS_RED(x) (!RBT_IS_BLACK(x))
#define RBT_COLOR_ASSIGN(a,b) (RBT_COLOR(a) = RBT_COLOR(b))
// ----------------------------------------
// visited node <- bit[1:2]
#define RBT_VISIT_FLAG_MASK (0x06)
#define RBT_VISIT_FLAG_LEFT (0x04)
#define RBT_VISIT_FLAG_RIGHT (0x02)
#define RBT_VISIT_CLR(x) (RBT_COLOR(x) &= ~RBT_VISIT_FLAG_MASK)
#define RBT_VISIT_LEFT(x) (RBT_COLOR(x) |= RBT_VISIT_FLAG_LEFT)
#define RBT_VISIT_RIGHT(x) (RBT_COLOR(x) |= RBT_VISIT_FLAG_RIGHT)
#define RBT_IS_VISITED_LEFT(x) (((RBT_COLOR(x) & RBT_VISIT_FLAG_LEFT) == RBT_VISIT_FLAG_LEFT)?\
true:false)
#define RBT_IS_VISITED_RIGHT(x) (((RBT_COLOR(x) & RBT_VISIT_FLAG_RIGHT) == RBT_VISIT_FLAG_RIGHT)?\
true:false)
/**
* º¯ÊýÉùÃ÷
*/
static bool rbtree_insert_fixup(prbtree_t head, prbtree_node_t tree);
static bool rbtree_delete_fixup(prbtree_t head, prbtree_node_t tree);
bool rbtree_init(prbtree_t *head)
{
*head = (prbtree_t)malloc(sizeof(rbtree_t));
if (*head == NULL)
{
return false;
}
(*head)->tree = NULL;
(*head)->size = 0;
return true;
}
void rbtree_destroy(prbtree_t * head)
{
if (*head != NULL)
{
rbtree_clear(*head);
free(*head);
*head = NULL;
}
}
bool rbtree_empty(prbtree_t head)
{
return ((head == NULL) || (head->tree == NULL)) ? true : false;
}
void rbtree_clear(prbtree_t head)
{
pqueue_t queue;
prbtree_node_t root;
prbtree_node_t tree_node;
if ((head == NULL) || head->tree == NULL)
{
return;
}
root = head->tree;
queue_init(&queue);
queue_in(queue, root);
while (!queue_empty(queue))
{
queue_out(queue, &tree_node);
if (tree_node->left != NULL)
{
queue_in(queue, tree_node->left);
}
if (tree_node->right != NULL)
{
queue_in(queue, tree_node->right);
}
free(tree_node);
tree_node = NULL;
}
queue_destroy(&queue);
head->tree = NULL;
head->size = 0;
}
uint32_t rbtree_get_size(prbtree_t head)
{
return head->size;
}
static prbtree_node_t rbtree_find(prbtree_t head, rbtree_data_t data)
{
prbtree_node_t root;
if ((head == NULL) || head->tree == NULL)
{
return NULL;
}
root = head->tree;
while (root != NULL)
{
if (data < root->data)
{
if (root->left != NULL)
{
root = root->left;
}
else
{
return root;
}
}
else if (data > root->data)
{
if (root->right != NULL)
{
root = root->right;
}
else
{
return root;
}
}
else
{
// ==
return root;
}
}
return root;
}
static prbtree_node_t get_parent_node(prbtree_node_t tree)
{
if (tree == NULL)
{
return NULL;
}
return tree->parent;
}
bool rbtree_insert(prbtree_t head, rbtree_data_t data)
{
prbtree_node_t tree_node;
prbtree_node_t new_node;
if (head == NULL)
{
return false;
}
// no root of tree
if (head->tree == NULL)
{
new_node = (prbtree_node_t)malloc(sizeof(rbtree_node_t));
if (new_node == NULL)
{
return false;
}
new_node->data = data;
new_node->left = NULL;
new_node->right = NULL;
new_node->parent = NULL; // the parent of root is NULL
RBT_COLOR_INIT(new_node);
head->tree = new_node;
}
else
{
tree_node = rbtree_find(head, data);
if (data < tree_node->data)
{
new_node = (prbtree_node_t)malloc(sizeof(rbtree_node_t));
if (new_node == NULL)
{
return false;
}
new_node->data = data;
new_node->left = NULL;
new_node->right = NULL;
new_node->parent = tree_node;
RBT_COLOR_INIT(new_node);
tree_node->left = new_node;
}
else if(data > tree_node->data)
{
new_node = (prbtree_node_t)malloc(sizeof(rbtree_node_t));
if (new_node == NULL)
{
return false;
}
new_node->data = data;
new_node->left = NULL;
new_node->right = NULL;
new_node->parent = tree_node;
RBT_COLOR_INIT(new_node);
tree_node->right = new_node;
}
else
{
// ÈôkeyÏàµÈ£¬Õý³£À´ËµÓ¦¸ÃÌæ»»valueÖµ¡£
// ÕâÀïµÄ´úÂë½ö½öÊǸö¹¤³Ì¼òµ¥¹¤³ÌʾÀý£¬
// dataÇø¾ÍÒ»¸öÊý¾Ý£¬Òò´Ë´Ë´¦Ö±½ÓºöÂÔ¡£
return true;
}
}
rbtree_insert_fixup(head, new_node);
if (head->size < _UI32_MAX)
{
head->size++;
}
return true;
}
static prbtree_node_t rbtree_turn_left(prbtree_node_t tree)
{
// ÒÔµ±Ç°½ÚµãΪÖÐÐÄÐýת
// ×¢Ò⸸½Úµã²¢²»¶¯£¬Ö»ÊÇΪÁËÁ¬½ÓеÄ×Ó½Úµã
//
prbtree_node_t node_n; // µ±Ç°½Úµã
prbtree_node_t node_nr; // µ±Ç°½ÚµãµÄÓÒ×Ó½Úµã
prbtree_node_t node_p; // µ±Ç°½ÚµãµÄ¸¸½Úµã
if (tree == NULL)
{
return NULL;
}
node_n = tree;
node_nr = node_n->right;
node_p = node_n->parent;
// 1. ¸üÐÂnode_p×Ó½Úµã
if (node_p != NULL)
{
// not root of tree
if (node_p->left == node_n)
{
node_p->left = node_nr;
}
else
{
node_p->right = node_nr;
}
}
node_nr->parent = node_p;
// 2. Ðýת
node_n->parent = node_nr; // ²»ÄÜÖ±½Ónode_p=node_nr£¬Ô­ÒòÄã¶®µÄ
node_n->right = node_nr->left;
node_nr->left = node_n;
if (node_n->right != NULL)
{
node_n->right->parent = node_n;
}
// 3. ·µ»ØÐµĽڵã
return node_nr;
}
static prbtree_node_t rbtree_turn_right(prbtree_node_t tree)
{
// ÒÔµ±Ç°½ÚµãΪÖÐÐÄÐýת
// ×¢Ò⸸½Úµã²¢²»¶¯£¬Ö»ÊÇΪÁËÁ¬½ÓеÄ×Ó½Úµã
//
prbtree_node_t node_n; // µ±Ç°½Úµã
prbtree_node_t node_nl; // µ±Ç°½ÚµãµÄ×ó×Ó½Úµã
prbtree_node_t node_p; // µ±Ç°½ÚµãµÄ¸¸½Úµã
if (tree == NULL)
{
return NULL;
}
node_n = tree;
node_nl = node_n->left;
node_p = node_n->parent;
// 1. ¸üÐÂnode_p×Ó½Úµã
if (node_p != NULL)
{
// not node_n
if (node_p->left == node_n)
{
node_p->left = node_nl;
}
else
{
node_p->right = node_nl;
}
}
node_nl->parent = node_p;
// 2. Ðýת
node_n->parent = node_nl; // ²»ÄÜÖ±½Ónode_p=node_nl£¬Ô­ÒòÄã¶®µÄ
node_n->left = node_nl->right;
node_nl->right = node_n;
if (node_n->left != NULL)
{
node_n->left->parent = node_n;
}
// 3. ·µ»ØÐµĽڵã
return node_nl;
}
static bool rbtree_insert_fixup(prbtree_t head, prbtree_node_t tree)
{
prbtree_node_t father, grandfather, uncle;
if ((head == NULL) || head->tree == NULL)
{
return false;
}
if (tree == NULL)
{
return false;
}
// ---------------------------------------
// case1.¸ù½Úµã²»´æÔÚ£¬ÔòÖ±½Ó²åÈëºÚÉ«½Úµã
// case2.¸¸½ÚµãΪºÚ£¬²åÈëºìÉ«½Úµã½Ô¿É
// £¨ÒÔÉÏÁ½ÖÖÇé¿ö£¬Òª½áºÏinsertº¯ÊýÀí½â£©
// case3.Ö÷Òª·ÖΪÈýÖÖÇé¿ö¿¼ÂÇ£¬ÈçÏÂ
// £¨×óÓҶԳƣ¬Àí½âÁË×óÈý£¬ÔòÓÒÈýÒ²¾Í²»ÄÑÁË£©
// ----------------------------------------
while (tree->parent != NULL && RBT_IS_RED(tree->parent))
{
father = get_parent_node(tree);
grandfather = get_parent_node(father);
if (father == grandfather->left)
{
uncle = grandfather->right;
if (uncle != NULL && RBT_IS_RED(uncle))
{
RBT_SET_BLACK(father);
RBT_SET_BLACK(uncle);
RBT_SET_RED(grandfather);
tree = grandfather;
}
else
{
if (tree == father->right)
{
tree = rbtree_turn_left(father);
RBT_SET_BLACK(tree);
}
else
{
RBT_SET_BLACK(father);
}
RBT_SET_RED(grandfather);
tree = rbtree_turn_right(grandfather);
break;
}
}
else
{
uncle = grandfather->left;
if (uncle != NULL && RBT_IS_RED(uncle))
{
RBT_SET_BLACK(father);
RBT_SET_BLACK(uncle);
RBT_SET_RED(grandfather);
tree = grandfather;
}
else
{
if (tree == father->left)
{
tree = rbtree_turn_right(father);
RBT_SET_BLACK(tree);
}
else
{
RBT_SET_BLACK(father);
}
RBT_SET_RED(grandfather);
tree = rbtree_turn_left(grandfather);
break;
}
}
}
if (tree->parent == NULL)
{
head->tree = tree;
RBT_SET_BLACK(head->tree);
}
return true;
}
static prbtree_node_t tree_get_node_min(prbtree_node_t tree)
{
while (tree != NULL)
{
if (tree->left != NULL)
{
tree = tree->left;
}
else
{
return tree;
}
}
return tree;
}
bool rbtree_delete(prbtree_t head, rbtree_data_t data)
{
prbtree_node_t tree_node; //µ±Ç°±¾¸Ãɾ³ýµÄ½Úµã
prbtree_node_t tree_node_del; //ʵ¼ÊÉϱ»É¾³ýµÄ½Úµã
if ((head == NULL) || head->tree == NULL)
{
return false;
}
tree_node = rbtree_find(head, data);
if (tree_node == NULL)
{
return false;
}
if (tree_node->data != data)
{
// ûÓÐÕÒµ½¸Ã²ÎÊý
return false;
}
if (tree_node->left == NULL && tree_node->right == NULL)
{
tree_node_del = tree_node;
}
else if (tree_node->left != NULL && tree_node->right == NULL)
{
tree_node_del = tree_node->left;
tree_node->data = tree_node_del->data;
}
else if (tree_node->left == NULL && tree_node->right != NULL)
{
tree_node_del = tree_node->right;
tree_node->data = tree_node_del->data;
}
else
{
// Ë«×Ó¶¼ÔÚ£¬Ôò²éÕÒºó¼Ì½Úµã
tree_node_del = tree_get_node_min(tree_node->right);
tree_node->data = tree_node_del->data;
if (tree_node_del->right != NULL)
{
// ±Øºì
tree_node_del->data = tree_node_del->right->data;
tree_node_del = tree_node_del->right;
}
}
if (RBT_IS_BLACK(tree_node_del))
{
rbtree_delete_fixup(head, tree_node_del);
}
// ´ÓtreeÖÐɾ³ý
if (tree_node_del->parent != NULL)
{
if (tree_node_del == tree_node_del->parent->left)
{
tree_node_del->parent->left = NULL;
}
else
{
tree_node_del->parent->right = NULL;
}
}
else
{
// ÈôΪ¸ù½Úµã
head->tree = NULL;
}
// ÊÍ·ÅÄÚ´æ
free(tree_node_del);
if (head->size > 0)
{
head->size--;
}
return true;
}
static bool rbtree_delete_fixup(prbtree_t head, prbtree_node_t tree)
{
prbtree_node_t node_temp = NULL;
prbtree_node_t father, brother;
if ((head == NULL) || head->tree == NULL)
{
return false;
}
while ((tree->parent != NULL) && RBT_IS_BLACK(tree))
{
father = get_parent_node(tree);
if (tree == father->left)
{
brother = father->right;
if (RBT_IS_RED(brother))
{
// ¸ù¾ÝrbtreeÐÔÖÊ£¬¸¸½Úµã±Ø¶¨ÎªºÚ£¬
// ºìbrotherµÄ×Ó½ÚµãË«ºÚ»òÕßË«¿Õ
// case 5
RBT_SET_BLACK(brother);
RBT_SET_RED(father);
node_temp = rbtree_turn_left(father);
// ½Úµãδɾ³ýʱƽºâ£¬µ«ÊÇɾ³ýÖ®ºóÓÖ²»Æ½ºâÁË
// Òò´ËÐèÒª¼ÌÐøÅжÏ
}
else if(brother->right != NULL && RBT_IS_RED(brother->right))
{
// ºÚbother´æÔÚright½Úµã£¬²¢ÇÒΪºìÉ«µÄÇé¿ö
// ¸¸½ÚµãÑÕɫδ֪
// case 1 £¨½öÓÒ×Ӻ죩ºÍ case 3£¨Ë«×Ӻ죩 ±¾ÖÊÉÏÒ»Ñù
RBT_COLOR_ASSIGN(brother,father); //color(f) -> color(b)
RBT_SET_BLACK(father);
RBT_SET_BLACK(brother->right);
tree = rbtree_turn_left(father);
// ɾ³ý½ÚµãÖ®ºó£¬¿Ï¶¨Æ½ºâÁË£¬Òò´ËÍ˳ö
// ÁíÍ⣬·­×ªÖ®ºó£¬Èô¸ÕºÃÊǸù½Úµã¡£Ôò¸³Öµ¸øtree
// ·½±ãÑ­»·ÍâÃæÅжÏ
break;
}
else if(brother->left != NULL && RBT_IS_RED(brother->left))
{
// ºÚbother½öÓÐleft½Úµã£¬ÇÒleftΪºìÉ«,£¨ÇÒrigth²»ºìµÄÇé¿ö£©
// ¸¸½ÚµãÑÕɫδ֪
// case 2
// ×¢Ò⣺ÕâÑùд´úÂëµÄ»°£¬Ôò±ØÐëÔÚcase2ǰÏÈÅжÏcase1/case3
RBT_SET_RED(brother);
RBT_SET_BLACK(brother->left);
node_temp = rbtree_turn_right(brother);
// Ëæºóת»¯ÎªÁËcase 1
}
else
{
// ºÚbrotherµÄ×Ó½ÚµãΪ˫¿Õ»òË«ºÚ
// case 4
if(RBT_IS_BLACK(father))
{
// Èô¸¸½ÚµãΪºÚ£¬Ôò½«brotherȾΪºìÉ«£¬
// µ«ÊÇ×ÜÌåÊÇÉÙÁËÒ»ºÚ£¬Òò´ËÒÔ¸¸½ÚµãΪtreeÏòÉϵݹé
RBT_SET_RED(brother);
tree = father;
}
else
{
// brotherË«×Ó¿Õ£¬Ôò±íʾbrotherºÍ±»É¾³ýµÄ½Úµãƽºâ
// Òò´ËÖ±½Óת»»ÑÕÉ«¼´¿É
RBT_SET_RED(brother);
RBT_SET_BLACK(father);
// ɾ³ý½ÚµãÖ®ºó£¬¿Ï¶¨Æ½ºâÁË£¬Òò´ËÍ˳ö
break;
}
}
}
else
{
brother = father->left;
if (RBT_IS_RED(brother))
{
// ¸ù¾ÝrbtreeÐÔÖÊ£¬¸¸½Úµã±Ø¶¨ÎªºÚ£¬
// ºìbrotherµÄ×Ó½ÚµãË«ºÚ»òÕßË«¿Õ
// case 5
RBT_SET_BLACK(brother);
RBT_SET_RED(father);
node_temp = rbtree_turn_right(father);
// ½Úµãδɾ³ýʱƽºâ£¬µ«ÊÇɾ³ýÖ®ºóÓÖ²»Æ½ºâÁË
// Òò´ËÐèÒª¼ÌÐøÅжÏ
}
else if (brother->left != NULL && RBT_IS_RED(brother->left))
{
// ºÚbother´æÔÚleft½Úµã£¬²¢ÇÒΪºìÉ«µÄÇé¿ö
// ¸¸½ÚµãÑÕɫδ֪
// case 1 £¨½öÓÒ×Ӻ죩ºÍ case 3£¨Ë«×Ӻ죩 ±¾ÖÊÉÏÒ»Ñù
RBT_COLOR_ASSIGN(brother,father);
RBT_SET_BLACK(father);
RBT_SET_BLACK(brother->left);
tree = rbtree_turn_right(father);
// ɾ³ý½ÚµãÖ®ºó£¬¿Ï¶¨Æ½ºâÁË£¬Òò´ËÍ˳ö
// ÁíÍ⣬·­×ªÖ®ºó£¬Èô¸ÕºÃÊǸù½Úµã¡£Ôò¸³Öµ¸øtree
// ·½±ãÑ­»·ÍâÃæÅжÏ
break;
}
else if (brother->right != NULL && RBT_IS_RED(brother->right))
{
// ºÚbother´æÔÚright½Úµã£¬ÇÒrightΪºìÉ«¡££¨ÇÒleft²»ºìµÄÇé¿ö£©
// ¸¸½ÚµãÑÕɫδ֪
// case 2
// ×¢Ò⣺ÕâÑùд´úÂëµÄ»°£¬Ôò±ØÐëÔÚcase2ǰÏÈÅжÏcase1/case3
RBT_SET_RED(brother);
RBT_SET_BLACK(brother->right);
node_temp = rbtree_turn_left(brother);
// Ëæºóת»¯ÎªÁË case 1
}
else
{
// ºÚbrotherµÄ×Ó½ÚµãΪ˫¿Õ»òË«ºÚ
// case 4
if(RBT_IS_BLACK(father))
{
// Èô¸¸½ÚµãΪºÚ£¬Ôò½«brotherȾΪºìÉ«£¬
// µ«ÊÇ×ÜÌåÊÇÉÙÁËÒ»ºÚ£¬Òò´ËÒÔ¸¸½ÚµãΪtreeÏòÉϵݹé
RBT_SET_RED(brother);
tree = father;
}
else
{
// brotherË«×Ó¿Õ£¬Ôò±íʾbrotherºÍ±»É¾³ýµÄ½Úµãƽºâ
// Òò´ËÖ±½Óת»»ÑÕÉ«¼´¿É
RBT_SET_RED(brother);
RBT_SET_BLACK(father);
// ɾ³ý½ÚµãÖ®ºó£¬¿Ï¶¨Æ½ºâÁË£¬Òò´ËÍ˳ö
break;
}
}
}
// ÔÚ´¦Àí¹ý³ÌÖУ¬·ÀÖ¹¸ù½Úµã¶ªÊ§
if (node_temp != NULL && node_temp->parent == NULL)
{
head->tree = node_temp;
}
}
if (tree->parent == NULL)
{
head->tree = tree;
}
RBT_SET_BLACK(head->tree);
return true;
}
bool rbtree_get_min(prbtree_t head, rbtree_data_t *data)
{
prbtree_node_t root;
if ((head == NULL) || head->tree == NULL)
{
return false;
}
root = head->tree;
while (root != NULL)
{
if (root->left != NULL)
{
root = root->left;
}
else
{
*data = root->data;
return true;
}
}
return false;
}
bool rbtree_get_max(prbtree_t head, rbtree_data_t *data)
{
prbtree_node_t root;
if ((head == NULL) || head->tree == NULL)
{
return false;
}
root = head->tree;
while (root != NULL)
{
if (root->right != NULL)
{
root = root->right;
}
else
{
*data = root->data;
return true;
}
}
return false;
}
#if 1
void rbtree_traversal_depth_preorder(prbtree_t head, tree_data_disp_t tree_data_disp)
{
pstack_t stack;
prbtree_node_t root;
prbtree_node_t tree_node;
if ((head == NULL) || head->tree == NULL)
{
return;
}
root = head->tree;
stack_init(&stack);
tree_node = root;
while (!stack_empty(stack) || tree_node != NULL)
{
if (tree_node != NULL)
{
tree_data_disp(tree_node->data);
stack_push(stack, tree_node);
tree_node = tree_node->left;
}
else
{
stack_pop(stack, &tree_node);
tree_node = tree_node->right;
}
}
stack_destroy(&stack);
}
void rbtree_traversal_depth_inorder(prbtree_t head, tree_data_disp_t tree_data_disp)
{
pstack_t stack;
prbtree_node_t root;
prbtree_node_t tree_node;
if ((head == NULL) || head->tree == NULL)
{
return;
}
root = head->tree;
stack_init(&stack);
tree_node = root;
while (!stack_empty(stack) || tree_node != NULL)
{
if (tree_node != NULL)
{
stack_push(stack, tree_node);
tree_node = tree_node->left;
}
else
{
stack_pop(stack, &tree_node);
tree_data_disp(tree_node->data);
tree_node = tree_node->right;
}
}
stack_destroy(&stack);
}
void rbtree_traversal_depth_postorder(prbtree_t head, tree_data_disp_t tree_data_disp)
{
pstack_t stack;
pstack_t stack_disp;
prbtree_node_t root;
prbtree_node_t tree_node;
if ((head == NULL) || head->tree == NULL)
{
return;
}
root = head->tree;
stack_init(&stack);
stack_init(&stack_disp);
tree_node = root;
while (!stack_empty(stack) || tree_node != NULL)
{
if (tree_node != NULL)
{
stack_push(stack_disp, tree_node);
stack_push(stack, tree_node);
tree_node = tree_node->right;
}
else
{
stack_pop(stack, &tree_node);
tree_node = tree_node->left;
}
}
while (!stack_empty(stack_disp))
{
stack_pop(stack_disp, &tree_node);
tree_data_disp(tree_node->data);
}
stack_destroy(&stack);
stack_destroy(&stack_disp);
}
#else
// -------------------------------------------------
// ·½Ê½2 ½èÖúÁË·ÃÎʱêÖ¾£¬²»¹ýÓиöÓÅÊÆ£¬·½±ã¼ÆËã¸ß¶È
// -------------------------------------------------
void rbtree_traversal_depth_preorder(prbtree_t head, tree_data_disp_t tree_data_disp)
{
pstack_t stack;
prbtree_node_t root;
prbtree_node_t tree_node;
if ((head == NULL) || head->tree == NULL)
{
return;
}
root = head->tree;
stack_init(&stack);
stack_push(stack, root);
tree_data_disp(root->data);
while (!stack_empty(stack))
{
stack_get_top(stack, &tree_node);
if (tree_node->left != NULL && !RBT_IS_VISITED_LEFT(tree_node))
{
RBT_VISIT_LEFT(tree_node);
stack_push(stack, tree_node->left);
tree_node = tree_node->left;
tree_data_disp(tree_node->data);
}
else if (tree_node->right != NULL && !RBT_IS_VISITED_RIGHT(tree_node))
{
RBT_VISIT_RIGHT(tree_node);
stack_push(stack, tree_node->right);
tree_node = tree_node->right;
tree_data_disp(tree_node->data);
}
else
{
RBT_VISIT_CLR(tree_node);
stack_pop(stack, &tree_node);
}
}
stack_destroy(&stack);
}
void rbtree_traversal_depth_inorder(prbtree_t head, tree_data_disp_t tree_data_disp)
{
pstack_t stack;
prbtree_node_t root;
prbtree_node_t tree_node;
if ((head == NULL) || head->tree == NULL)
{
return;
}
root = head->tree;
stack_init(&stack);
stack_push(stack, root);
while (!stack_empty(stack))
{
stack_get_top(stack, &tree_node);
if (tree_node->left != NULL && !RBT_IS_VISITED_LEFT(tree_node))
{
RBT_VISIT_LEFT(tree_node);
stack_push(stack, tree_node->left);
tree_node = tree_node->left;
}
else if (tree_node->right != NULL && !RBT_IS_VISITED_RIGHT(tree_node))
{
RBT_VISIT_RIGHT(tree_node);
tree_data_disp(tree_node->data);
stack_push(stack, tree_node->right);
tree_node = tree_node->right;
}
else
{
if (!RBT_IS_VISITED_RIGHT(tree_node))
{
tree_data_disp(tree_node->data);
}
RBT_VISIT_CLR(tree_node);
stack_pop(stack, &tree_node);
}
}
stack_destroy(&stack);
}
void rbtree_traversal_depth_postorder(prbtree_t head, tree_data_disp_t tree_data_disp)
{
pstack_t stack;
prbtree_node_t root;
prbtree_node_t tree_node;
if ((head == NULL) || head->tree == NULL)
{
return;
}
root = head->tree;
stack_init(&stack);
stack_push(stack, root);
while (!stack_empty(stack))
{
stack_get_top(stack, &tree_node);
if (tree_node->left != NULL && !RBT_IS_VISITED_LEFT(tree_node))
{
RBT_VISIT_LEFT(tree_node);
stack_push(stack, tree_node->left);
tree_node = tree_node->left;
}
else if (tree_node->right != NULL && !RBT_IS_VISITED_RIGHT(tree_node))
{
RBT_VISIT_RIGHT(tree_node);
stack_push(stack, tree_node->right);
tree_node = tree_node->right;
}
else
{
RBT_VISIT_CLR(tree_node);
stack_pop(stack, &tree_node);
tree_data_disp(tree_node->data);
}
}
stack_destroy(&stack);
}
#endif
void rbtree_traversal_breadth(prbtree_t head, tree_data_disp_t tree_data_disp)
{
pqueue_t queue;
prbtree_node_t root;
prbtree_node_t tree_node;
if ((head == NULL) || head->tree == NULL)
{
return;
}
root = head->tree;
queue_init(&queue);
queue_in(queue, root);
if (root != NULL)
{
while (!queue_empty(queue))
{
queue_out(queue, &tree_node);
if (tree_node->left != NULL)
{
queue_in(queue, tree_node->left);
}
if (tree_node->right != NULL)
{
queue_in(queue, tree_node->right);
}
tree_data_disp(tree_node->data);
}
}
queue_destroy(&queue);
}
static bool rbtree_node_check(prbtree_node_t tree_node)
{
// check
if (tree_node->parent == NULL)
{
if (RBT_IS_RED(tree_node))
{
return false;
}
}
else
{
if (RBT_IS_RED(tree_node))
{
if (tree_node->left != NULL && tree_node->right != NULL)
{
if (RBT_IS_RED(tree_node->left) || RBT_IS_RED(tree_node->right))
{
// error
return false;
}
}
else if (tree_node->left != NULL && tree_node->right == NULL)
{
// error
return false;
}
else if (tree_node->left == NULL && tree_node->right != NULL)
{
// error
return false;
}
else
{
// pass
}
}
else
{
if (tree_node->left != NULL && tree_node->right == NULL)
{
if (RBT_IS_BLACK(tree_node->left))
{
// error
return false;
}
}
else if (tree_node->left == NULL && tree_node->right != NULL)
{
if (RBT_IS_BLACK(tree_node->right))
{
// error
return false;
}
}
else
{
// pass
}
}
}
return true;
}
bool rbtree_check(prbtree_t head)
{
pstack_t stack;
prbtree_node_t root;
prbtree_node_t tree_node;
bool ret = true;
uint32_t black_cnt = 0, black_cnt_max = 0;
if ((head == NULL) || head->tree == NULL)
{
// ok
return ret;
}
root = head->tree;
if (RBT_IS_RED(root))
{
ret = false;
return ret;
}
else
{
black_cnt++;
if (black_cnt > black_cnt_max)
{
black_cnt_max = black_cnt;
}
}
stack_init(&stack);
stack_push(stack, root);
while (!stack_empty(stack))
{
stack_get_top(stack,&tree_node);
if (tree_node->left != NULL && !RBT_IS_VISITED_LEFT(tree_node))
{
RBT_VISIT_LEFT(tree_node);
stack_push(stack, tree_node->left);
tree_node = tree_node->left;
if (RBT_IS_BLACK(tree_node))
{
black_cnt++;
if (black_cnt > black_cnt_max)
{
black_cnt_max = black_cnt;
}
}
}
else if (tree_node->right != NULL && !RBT_IS_VISITED_RIGHT(tree_node))
{
RBT_VISIT_RIGHT(tree_node);
stack_push(stack, tree_node->right);
tree_node = tree_node->right;
if (RBT_IS_BLACK(tree_node))
{
black_cnt++;
if (black_cnt > black_cnt_max)
{
black_cnt_max = black_cnt;
}
}
}
else
{
if (tree_node->left == NULL && tree_node->right == NULL)
{
if (black_cnt != black_cnt_max)
{
ret = false;
goto black_check_exit;
}
}
RBT_VISIT_CLR(tree_node);
stack_pop(stack, &tree_node);
if (RBT_IS_BLACK(tree_node))
{
if (black_cnt > 0)
{
black_cnt--;
}
}
// check node
if (true != rbtree_node_check(tree_node))
{
ret = false;
goto black_check_exit;
}
}
}
black_check_exit:
stack_destroy(&stack);
return ret;
}
#endif // RBTREE == 1