要实现红黑树节点的插入删除,得先实现二叉树节点插入删除,在这基础上加入红黑树调整算法。
今天早上编写了二叉树的节点删除代码。结果如下
实践经验:
1.要删除节点,得先遍历出节点位置,我用数组存放遍历出来的结果。然后删除结果中倒数第三个数字时,遇到了困难:
(1)刚开始直接用mid_travel算法遍历,发现递归的时候,要传递数组指针,且让指针地址增加,不好处理。
(2)然后我加入了get_tree_array函数,想通过“指针的指针”来存指针,以为记住最开始的数组指针地址,然后让指针在递归的时候,自行递增。还是失败了。这样无法保证递归的时候,数组的下标位置。在递归的时候,很难判断什么时候加1,如果要做这步,还得统计子树的左右子树数目,然后根据子节点数目增加当前节点的指针地址。这样很繁琐。
(3)于是,我加入了suffix(数组下标),这就解决了递归的时候,判断指针位置的繁琐处理。
2.很多操作用独立函数代替,不但逻辑看起来会更清晰,而且可以重用,一举两得。函数看起来很多,其实都是互相嵌套的,其实可以用一个函数写完。
红黑树插入算法实践经验
(1)昨天写好了红黑树算法,调试了一下午,发现打印出来的树不对。
原因1是NULL改为哨兵节点Nil,很多判断要用哨兵的值来取代。
原因2今天才发现,root会因为旋转操作而改变位置,如果我像打印二叉树那样打印最初的root,很可能只打印了一半。举例:最初的root是99,它是我随机产生的数(0~99)中最大的,它一定会是右叶子节点 。这样,我如果以最初的root打印树,只有1个节点。由于没考虑这个特性,我还一直找bug,直到调试时候,自己认真跟踪数值变化,才发现。
调试信息如下,供参考
init_rb_root: mNil =0x1956030;root =0x1956060
root is 65
************insert_node*************
i = 1 ,root=0x1956060
insert_node : befor insert : pNode->left->value = -1
insert_node : insert left:46
insert fixup
i = 2 ,root=0x1956060
insert_node : befor insert : pNode->left->value = -1
insert_node : insert left:35
insert fixup
case 1
PARENT_SIDE = LEFT
case 2
case 3
right_rotate:
i = 3 ,root=0x1956060
insert_node : befor insert : pNode->left->value = -1
insert_node : insert left:56
insert fixup
case 1
PARENT_SIDE = RIGHT
i = 4 ,root=0x1956060
insert_node : befor insert : pNode->left->value = -1
insert_node : insert left:8
insert fixup
case 1
PARENT_SIDE = LEFT
case 2
case 3
right_rotate:
i = 5 ,root=0x1956060
insert_node : befor insert : pNode->left->value = -1
insert_node : insert left:38
insert fixup
case 1
PARENT_SIDE = RIGHT
i = 6 ,root=0x1956060
************insert_node*************
get_tree_height: pRoot = 0x1956060;value = 65
get_tree_height: pRoot = 0x19561b0;value = 38
get_tree_height: pRoot = 0x1956030;value = -1
get_tree_height: pRoot = 0x1956030;value = -1
get_tree_height: pRoot = 0x1956030;value = -1
creat tree succuess!Tree heigh is:2
get_tree_height: pRoot = 0x1956060;value = 65
get_tree_height: pRoot = 0x19561b0;value = 38
get_tree_height: pRoot = 0x1956030;value = -1
get_tree_height: pRoot = 0x1956030;value = -1
get_tree_height: pRoot = 0x1956030;value = -1
print_tree: height = 2
print_tree :Nil(pRoot->parent) = 0x1956120
_______________________
breath begin,enter root:
65B
__||__
38R ooB
-----------
breath end!
-----------
所以,创建树的办法和二叉树不一样,因为root不是固定的。之前的代码是这样的,要更改
Tree create_tree(int num)
{
srand(time(NULL));
Tree root = init_rb_root(rand()%100);
printf("root is %d\n",root->value);
int i ;
printf("************insert_node*************\n");
for(i=1;i<num;i++)
{
printf("i = %d ,root=%p\n",i,root);
insert_node(root,rand()%100);
}
printf("************insert_node*************\n");
printf("creat tree succuess!Tree heigh is:%d\n",get_tree_height(root));
return root ;
}
~
增加get_root函数,每次for循环,根据最初的root去找新的root。打印新的root就可以了
如
Tree create_tree(int num,Queue *pQueue)
{
srand(time(NULL));
Tree root = init_rb_root(rand()%100);
Tree new_root = root;
printf("root is %d\n",root->value);
int i ;
for(i=1;i<num;i++)
{
// printf("i = %d ,root=%p\n",i,root);
// printf("new_root = %p\n",new_root);
insert_node(new_root,rand()%100);
new_root = get_root(root);
print_tree(new_root,pQueue);
}
// printf("new_root->value = %d\n",new_root->value);
printf("creat tree succuess!Tree heigh is:%d\n",get_tree_height(new_root));
return new_root ;
}
红黑树插入过程如下,oo是NULL节点,为了方便,我把NULL当成节点打印出来了。就是说,队列中有NULL节点,但是树里面不存在指向Nil节点的Nil节点。R是红色,B是黑色
http://blog.csdn.net/xzongyuan/article/details/22934103
代码在把红黑树写好后,再发上来,估计要花点时间。
编辑中。。。