红黑树的实现与应用

来源:互联网 发布:银鼎天贵金属行情软件 编辑:程序博客网 时间:2024/06/11 17:08

正如这篇博文中说到的金山网络面试经历  http://blog.csdn.net/huruzun/article/details/24634593  面试官要自己设计数据结构实现容器类,需要尽快的实现插入删除查找,在现实实现STL 容器类中红黑树被广泛的应用。

平衡二叉树(BalancedBinary Tree或Height-Balanced Tree)又称AVL树。它或者是一棵空树,或者是具有下列性质的二叉树:它的左子树和右子树都是平衡二叉树,且左子树和右子树的深度之差的绝对值不超过1。若将二叉树上结点的平衡因子BF(BalanceFactor)定义为该结点的左子树的深度减去它的右子树的深度,则平衡二叉树上所有结点的平衡因子只可能是-1、0和1。(此段定义来自严蔚敏的《数据结构(C语言版)》)

红黑树严格意义上不满足平衡因子绝对值小于等于1情况,下面代码就进行测试。

我们知道一颗高度为h的二叉查找树可以实现任何一种基本的动态集合操作,其时间复杂度为 O(h)。这样在树高度比较低时,基本动态操作如插入、删除 会执行的很快,但是当树的高度较高是,尤其是极端情况下的树结构 退化成链表插入删除效率。如上面所说红黑树是许多“平衡的”的查找树中一种,它能保证在最坏情况下,基本动态集合操作的时间为 O(lgn)n 为树结点数目。

本文代码实现参考下面两篇博文感谢作者:http://blog.csdn.net/npy_lp/article/details/7420689

http://blog.csdn.net/v_JULY_v/article/details/6114226    JULY 博客强力推荐,他对算法理解很好。

 

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <iostream>using namespace std;typedef int key_t;typedef int data_t;typedef enum color_t{RED = 0,BLACK = 1}color_t;typedef struct rb_node_t{struct rb_node_t *left, *right, *parent;key_t key;data_t data;color_t color;}rb_node_t;/* forward declaration */rb_node_t* rb_insert(key_t key, data_t data, rb_node_t* root);rb_node_t* rb_search(key_t key, rb_node_t* root);rb_node_t* rb_erase(key_t key, rb_node_t* root);static rb_node_t* rb_rotate_left(rb_node_t* node, rb_node_t* root){rb_node_t* right = node->right;if ((node->right = right->left))//注意括号里面只是一个等号{right->left->parent = node;}right->left = node;if ((right->parent = node->parent)){if (node == node->parent->right){node->parent->right = right;}else{node->parent->left = right;}}else{root = right;}node->parent = right;return root;}static rb_node_t* rb_rotate_right(rb_node_t* node, rb_node_t* root){rb_node_t* left = node->left;if ((node->left = left->right)){left->right->parent = node;}left->right = node;if ((left->parent = node->parent)){if (node == node->parent->right){node->parent->right = left;}else{node->parent->left = left;}}else{root = left;}node->parent = left;return root;}static rb_node_t* rb_insert_rebalance(rb_node_t *node, rb_node_t *root){rb_node_t *parent, *gparent, *uncle, *tmp;//循环大的控制条件是 node 的 parent 颜色是红色才进入循环处理while ((parent = node->parent) && parent->color == RED){gparent = parent->parent;if (parent == gparent->left){uncle = gparent->right;//情况 1 node的叔叔是红色的情况if (uncle && uncle->color == RED){uncle->color = BLACK;parent->color = BLACK;gparent->color = RED;node = gparent;}//情况 2 ,3 node 的叔叔是黑色的else{//情况 2 node 是parent的右孩子 if (parent->right == node){root = rb_rotate_left(parent, root);// 左旋过后 交换 parent与node 位置tmp = parent;parent = node;node = tmp;}//情况 3 node 是parent的左孩子 parent->color = BLACK;gparent->color = RED;root = rb_rotate_right(gparent, root);}}// 算法导论中写道 :same as then with "right" and "left" exchanged 下面代码实现类似,只是把left换成 rightelse{uncle = gparent->left;if (uncle && uncle->color == RED){uncle->color = BLACK;parent->color = BLACK;gparent->color = RED;node = gparent;}else{if (parent->left == node){root = rb_rotate_right(parent, root);tmp = parent;parent = node;node = tmp;}parent->color = BLACK;gparent->color = RED;root = rb_rotate_left(gparent, root);}}}root->color = BLACK;return root;}static rb_node_t* rb_new_node(key_t key, data_t data){rb_node_t *node = (rb_node_t*)malloc(sizeof(struct rb_node_t));if (!node){printf("malloc error!\n");exit(-1);}node->key = key, node->data = data;return node;}static rb_node_t* rb_search_auxiliary(key_t key, rb_node_t* root, rb_node_t** save){rb_node_t *node = root, *parent = NULL;int ret;while (node){parent = node;ret = node->key - key;if (0 < ret){node = node->left;}else if (0 > ret){node = node->right;}else{return node;}}if (save){*save = parent;}return NULL;}rb_node_t* rb_insert(key_t key, data_t data, rb_node_t* root){rb_node_t *parent = NULL, *node;parent = NULL;if ((node = rb_search_auxiliary(key, root, &parent)))//函数返回node需要插入的位置,并且更新parent为node的parent{return root;//node 已经存在情况直接返回}node = rb_new_node(key, data);//产生新结点函数,更好实现模块化//新插入节点left right 指向NULL ,颜色给成红色node->parent = parent;node->left = node->right = NULL;node->color = RED;// 使得parent 指向 node结点if (parent){if (parent->key > key){parent->left = node;}else{parent->right = node;}}else{root = node;}return rb_insert_rebalance(node, root);}rb_node_t* rb_search(key_t key, rb_node_t* root){return rb_search_auxiliary(key, root, NULL);}static rb_node_t* rb_erase_rebalance(rb_node_t *node, rb_node_t *parent, rb_node_t *root){rb_node_t *other, *o_left, *o_right;while ((!node || node->color == BLACK) && node != root){if (parent->left == node){other = parent->right;if (other->color == RED){other->color = BLACK;parent->color = RED;root = rb_rotate_left(parent, root);other = parent->right;}if ((!other->left || other->left->color == BLACK) &&(!other->right || other->right->color == BLACK)){other->color = RED;node = parent;parent = node->parent;}else{if (!other->right || other->right->color == BLACK){if ((o_left = other->left)){o_left->color = BLACK;}other->color = RED;root = rb_rotate_right(other, root);other = parent->right;}other->color = parent->color;parent->color = BLACK;if (other->right){other->right->color = BLACK;}root = rb_rotate_left(parent, root);node = root;break;}}else{other = parent->left;if (other->color == RED){other->color = BLACK;parent->color = RED;root = rb_rotate_right(parent, root);other = parent->left;}if ((!other->left || other->left->color == BLACK) &&(!other->right || other->right->color == BLACK)){other->color = RED;node = parent;parent = node->parent;}else{if (!other->left || other->left->color == BLACK){if ((o_right = other->right)){o_right->color = BLACK;}other->color = RED;root = rb_rotate_left(other, root);other = parent->left;}other->color = parent->color;parent->color = BLACK;if (other->left){other->left->color = BLACK;}root = rb_rotate_right(parent, root);node = root;break;}}}if (node){node->color = BLACK;}return root;}rb_node_t* rb_erase(key_t key, rb_node_t *root){rb_node_t *child, *parent, *old, *left, *node;color_t color;//先查找删除结点值是否存在if (!(node = rb_search_auxiliary(key, root, NULL))){printf("key %d is not exist!\n");return root;}old = node;if (node->left && node->right){node = node->right;while ((left = node->left) != NULL){node = left;}child = node->right;parent = node->parent;color = node->color;if (child){child->parent = parent;}if (parent){if (parent->left == node){parent->left = child;}else{parent->right = child;}}else{root = child;}if (node->parent == old){parent = node;}node->parent = old->parent;node->color = old->color;node->right = old->right;node->left = old->left;if (old->parent){if (old->parent->left == old){old->parent->left = node;}else{old->parent->right = node;}}else{root = node;}old->left->parent = node;if (old->right){old->right->parent = node;}}else{if (!node->left){child = node->right;}else if (!node->right){child = node->left;}parent = node->parent;color = node->color;if (child){child->parent = parent;}if (parent){if (parent->left == node){parent->left = child;}else{parent->right = child;}}else{root = child;}}free(old);if (color == BLACK){root = rb_erase_rebalance(child, parent, root);}return root;}void inorder(rb_node_t *root){if (root!=NULL){inorder(root->left);cout<<"key="<<root->key<<" color="<<root->color<<endl;inorder(root->right);}}int main(){int test[6]={41,38,31,12,19,8};rb_node_t* root = NULL, *node = NULL;int i;for (i=0;i<6;i++){if ((root = rb_insert(test[i], i, root))){printf("[i = %d] insert key %d success!\n", i+1, test[i]);}else{printf("[i = %d] insert key %d error!\n", i+1, test[i]);exit(-1);}}inorder(root);return 0;}



main 函数测试了算法导论给的思考题。
如果读者不理解算法过程可以参考算法导论或者JULY博文:http://blog.csdn.net/v_JULY_v/article/details/6109153

0 0
原创粉丝点击