红黑树的实现

来源:互联网 发布:噪声分析软件 编辑:程序博客网 时间:2024/06/10 13:03

学了一下算法导论上的红黑树,这个数据结构基于二叉搜索树,二叉搜索树有一个缺点:如果数据以递增的顺序插入,得到的树深度就是n,进行操作就很不方便。红黑树就是在此基础上完善,自己可以自平衡,使两边始终保持接近,这样时间复杂度就降到O(lgn)。这个数据结构的确很难,插入和删除这两种操作非常复杂,自己按照书上给的伪代码实现了一下,思路是基本理清了,这种太复杂的数据结构想完全记住是不太现实的,能够掌握要点,下次看的时候可以马上回忆起来就可以了。

头文件:

#ifndef _RED_BLACK_TREE_#define _RED_BLACK_TREE_#define RED 82#define BLACK 66typedef struct RBTreeNode{unsigned int color;int key;struct RBTreeNode *left;struct RBTreeNode *right;struct RBTreeNode *pre;}Node,*RBTree;typedef struct RBRoot{Node *root;}RBRoot;RBRoot *CreateTree();void InsertTree(RBRoot *tree, int key);void DeleteNode(RBRoot *tree, Node *z);void PrintTree(RBRoot *tree);#endif

函数声明文件:

#include<iostream>#include<stdlib.h>#include"rbtree.h"static void LeftRotate(RBRoot *tree, Node *x);static void RightRotate(RBRoot *tree, Node *y);static void RBInsertFixUp(RBRoot *tree, Node *z);static void PrintNode(Node *node,int key, int direction);static void InsertNode(RBRoot *tree, Node *z);static void RBTransplant(RBRoot *tree, Node *u, Node *v);static void RBDeleteFixUp(RBRoot *tree, Node *x);RBRoot *CreateTree(){RBRoot *tree = (RBRoot *)malloc(sizeof(RBRoot));tree->root = NULL;return tree;}static void LeftRotate(RBRoot *tree, Node *x){Node *y = x->right;x->right = y->left;if (y->left != NULL)y->left->pre = x;y->pre = x->pre;if (x->pre == NULL)tree->root = y;else if (x == x->pre->left)x->pre->left = y;elsex->pre->right = y;y->left = x;x->pre = y;}static void RightRotate(RBRoot *tree, Node *y){Node *x = y->left;y->left = x->right;if (x->right != NULL)x->right->pre = y;x->pre = y->pre;if (y->pre == NULL)tree->root = x;else if (y == y->pre->left)y->pre->left = x;elsey->pre->right = x;y->pre = x;x->right = y;}static void RBInsertFixUp(RBRoot *tree, Node *z){while (z->pre!=NULL&&z->pre->pre!=NULL&&z->pre->color == RED)//自己和父亲都是红结点{if (z->pre == z->pre->pre->left){Node *y = z->pre->pre->right;if (y!=NULL&&y->color == RED)//叔也为红结点就把父亲和叔叔都变成红色,爷爷变成黑色,这样达到一个z变成爷爷上移的作用,且黑高不变{z->pre->color = BLACK;y->color = BLACK;z->pre->pre->color = RED;z = z->pre->pre;}else if (z == z->pre->right)//叔为黑且自己为右子树就进行一次左旋转换为第三种情况(叔不存在也是黑){z = z->pre;LeftRotate(tree, z);}else//将父亲和爷爷的颜色交换并对爷爷进行一次右旋,这样转换为第一种情况{z->pre->color = BLACK;z->pre->pre->color = RED;RightRotate(tree, z->pre->pre);}}else//父亲为右子树的情况只要把上面的情况中所以Right和Left互换就行{Node *y = z->pre->pre->left;if (y!=NULL&&y->color == RED){z->pre->color = BLACK;y->color = BLACK;z->pre->pre->color = RED;z = z->pre->pre;}else if (z == z->pre->left){z = z->pre;RightRotate(tree, z);}else{z->pre->color = BLACK;z->pre->pre->color = RED;LeftRotate(tree, z->pre->pre);}}}tree->root->color = BLACK;//将根结点设为黑色}static void InsertNode(RBRoot *tree, Node *z){Node *y = NULL;Node *x = tree->root;while (x != NULL)//寻找合适的位置{y = x;if (z->key < x->key)x = x->left;elsex = x->right;}z->pre = y;if (y == NULL)tree->root = z;else if (z->key < y->key)y->left = z;elsey->right = z;z->left = NULL;z->right = NULL;z->color = RED;RBInsertFixUp(tree, z);}static void PrintNode(Node *node,int key, int direction){if (node != NULL){if(direction==0)printf("%2d(B) is root\n", node->key);elseprintf("%2d(%c) is %2d's %6s child\n", node->key, node->color, key, direction == 1 ? "right" : "left");PrintNode(node->left, node->key, -1);PrintNode(node->right, node->key, 1);}}void PrintTree(RBRoot *tree){if (tree!=NULL&&tree->root != NULL)PrintNode(tree->root, tree->root->key, 0);}void InsertTree(RBRoot *tree, int key){Node* temp=(Node*)malloc(sizeof(Node));temp->key = key;temp->left = NULL;temp->right = NULL;temp->color = BLACK;InsertNode(tree, temp);}void RBTransplant(RBRoot *tree, Node *u, Node *v)//用v来取代u{if (u->pre == NULL)tree->root = v;else if (u == u->pre->left)u->pre->left = v;elseu->pre->right = v;v->pre = u->pre;}void RBDeleteFixUp(RBRoot *tree, Node *x){while (x != tree->root&&x->color == BLACK){if (x == x->pre->left){Node *w = x->pre->right;//x为y的右子树,w为x的兄弟if (w->color == RED)//情况1:兄弟为红色,左旋一次转换为情况2{w->color == BLACK;x->pre->color = RED;LeftRotate(tree, x->pre);w = x->pre->right;}else{if (w->left->color == BLACK&&w->right->color == BLACK)//情况2:兄弟的两个孩子都是黑色,将兄弟削去一层黑色,将x上移,转换为情况1234{w->color = RED;x = x->pre;}else if (w->right->color == BLACK)//情况3:兄弟的左孩子红右孩子黑,右旋一次转换为情况4{w->left->color = BLACK;w->color = RED;RightRotate(tree, w);w = x->pre->right;}else//情况4:兄弟的孩子都是红色,此时坐旋使原x的路径增加一个黑色,这种情况出现说明完成红黑平衡{w->color = x->pre->color;x->pre->color = BLACK;w->right->color = BLACK;LeftRotate(tree, x->pre);x = tree->root;}}}else{Node *w = x->pre->left;if (w->color == RED){w->color == BLACK;x->pre->color = RED;RightRotate(tree, x->pre);w = x->pre->left;}else{if (w->left->color == BLACK&&w->right->color == BLACK)//情况2:兄弟的两个孩子都是黑色,将兄弟削去一层黑色,将x上移,转换为情况1234{w->color = RED;x = x->pre;}else if (w->left->color == BLACK)//情况3:兄弟的左孩子红右孩子黑,右旋一次转换为情况4{w->right->color = BLACK;w->color = RED;LeftRotate(tree, w);w = x->pre->left;}else//情况4:兄弟的孩子都是红色,此时坐旋使原x的路径增加一个黑色,这种情况出现说明完成红黑平衡{w->color = x->pre->color;x->pre->color = BLACK;w->left->color = BLACK;RightRotate(tree, x->pre);x = tree->root;}}}}x->color = BLACK;}void DeleteNode(RBRoot *tree,Node *z){Node *y,*x;y = z;unsigned int origin_color = y->color;if (z->left == NULL){x = z->right;RBTransplant(tree, z, z->right);}else if (z->right == NULL){x = z->left;RBTransplant(tree, z, z->left);}else{Node *temp = z->right;while (temp->left!= NULL)temp = temp->left;y = temp;origin_color = y->color;x = y->right;if (y->pre == z)x->pre = y;else{RBTransplant(tree, y, y->right);y->right = z->right;y->right->pre = y;}RBTransplant(tree, z, y);y->left = z->left;y->left->pre = y;y->color = z->color;}if (origin_color == BLACK)RBDeleteFixUp(tree, x);}

实现文件:

#include<stdio.h>#include<stdlib.h>#include"rbtree.h"int main(){int test[] = { 10, 40,30,60,90,70,20,50,80};RBRoot* tree = CreateTree();for (int i = 0; i < sizeof(test)/sizeof(int); i++)InsertTree(tree, test[i]);PrintTree(tree);DeleteNode(tree,tree->root);PrintTree(tree);return 0;}




0 0