mirror of
https://gitee.com/apaki/unicstl.git
synced 2025-05-18 03:51:35 +08:00
1187 lines
22 KiB
C
1187 lines
22 KiB
C
|
||
#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
|
||
|