算法11---红黑树不带父结点指针的插入实现

算法11---红黑树不带父结点指针的插入实现

  1 #include <iostream>
  2 using namespace std;
  3 #define BLACK 0
  4 #define RED 1
  5 #define Nil -1
  6 #define LEN sizeof(struct Tree)
  7 struct Tree
  8 {
  9    struct Tree*left;
 10    struct Tree*right;
 11    int key;
 12    int color;
 13 };
 14 struct Tree*root=NULL;
 15 struct Tree*nil=NULL;
 16 //非递归版本的二叉查找树查找函数
 17 struct Tree*ITERATIVE_TREE_SEARCH(struct Tree*x,int k,struct Tree*&p1,struct Tree*&p2)
 18 {//
 19     while (x!=nil&&k!=x->key)
 20     {
 21         p1=x;
 22         if (k<x->key)
 23         {
 24             x=x->left;
 25         }
 26         else x=x->right;
 27         if(k!=x->key)//如果没找到了待查找值,那么继续记录其祖父和父结点值。
 28         {
 29             p2=p1;
 30             p1=x;
 31         }
 32     }
 33     return x;
 34 }
 35 void LEFT_ROTATE(struct Tree*T,struct Tree*x)
 36 {//左旋转:分三个步骤①②③来叙述旋转代码的。
 37     struct Tree*p1=nil,*p2=nil;
 38     struct Tree*y=x->right;//设置y结点。
 39     x->right=y->left;//本行代码以及下面的if结构表达的是“y的左孩子成为x的右孩子”。①
 40     ITERATIVE_TREE_SEARCH(root,x->key,p1,p2);
 41     if(p1==nil)//本行代码以及下面的if-else结构表达的过程是“y成为该子树新的根”。②
 42     {
 43        root=y;
 44     }
 45     else if(x==p1->left)
 46     {
 47        p1->left=y;
 48     }
 49     else p1->right=y;
 50     y->left=x;//本行代码以及下面一行都表达了“x成为y的左孩子”。③
 51 }
 52 void RIGHT_ROTATE(struct Tree*T,struct Tree*x)
 53 {//右旋转
 54     struct Tree*p1=nil,*p2=nil;
 55     struct Tree*y=x->left;
 56     x->left=y->right;
 57     ITERATIVE_TREE_SEARCH(root,x->key,p1,p2);
 58     if(p1==nil)
 59     {
 60         root=y;
 61     }
 62     else if(x==p1->right)
 63     {
 64         p1->right=y;
 65     }
 66     else p1->left=y;
 67     y->right=x;
 68 }
 69 void RB_INSERT_INSERT_FIXUP(struct Tree*T,struct Tree*z)
 70 {
 71    struct Tree*p1=nil,*p2=nil;
 72    ITERATIVE_TREE_SEARCH(root,z->key,p1,p2);//p1=z->parent,p2=z->parent->parent
 73    while (1)
 74    {
 75        ITERATIVE_TREE_SEARCH(root,z->key,p1,p2);//p1是父结点 p2是祖父结点
 76        if (p1->color!=RED)
 77        {
 78            break;
 79        }
 80        if (p1==p2->left)
 81        {
 82            struct Tree*y=p2->right;//叔结点
 83            if (y->color==RED)//情况一:叔结点为红色
 84            {//给p1,y,p2着色以保持性质5。并且解决了z的父结点和z都是红色结点问题
 85                p1->color=BLACK;
 86                y->color=BLACK;
 87                p2->color=RED;
 88                z=p2;//把z的祖父结点当成新结点z进入下一次循环
 89            }
 90            else
 91            {
 92                if (z==p1->right)//情况二:检查z是否是一个右孩子且叔结点为黑色,前提是p1结点不是叶子结点
 93                {//使用一个左旋让情况2转变为情况3
 94                    z=p1;
 95                    LEFT_ROTATE(T,z);//由于进入if语句后可知旋转结点不可能是叶子结点,这样就不用判断z是否是叶子结点了。
 96                 ITERATIVE_TREE_SEARCH(root,z->key,p1,p2);//p1=z->parent,p2=z->parent->parent
 97                }
 98                p1->color=BLACK;//情况三:是z是一个左孩子且叔结点为黑色,改变z的父和祖父结点颜色并做一次右旋,以保持性质5。
 99                p2->color=RED;
100                if(p2!=nil) RIGHT_ROTATE(T,p2);//由于p2可能是叶子结点,所以最好还是用一个if判断
101            }
102        }
103        else//下面else分支类似于上面
104        {
105            struct Tree*y=p2->left;
106            if (y->color==RED)
107            {
108                p1->color=BLACK;
109                y->color=BLACK;
110                p2->color=RED;
111                z=p2;
112            }
113            else
114            {
115                if (z==p1->left)
116                {
117                    z=p1;
118                    RIGHT_ROTATE(T,z);
119                    ITERATIVE_TREE_SEARCH(root,z->key,p1,p2);
120                }
121                p1->color=BLACK;
122                p2->color=RED;
123                if(p2!=nil) LEFT_ROTATE(T,p2);
124            }
125        }
126    }
127    root->color=BLACK;//最后给根结点着为黑色。
128 }
129 void RB_INSERT(struct Tree*T,struct Tree*z)
130 {
131     struct Tree*y=nil;
132     struct Tree*x=root;
133     while (x!=nil)
134     {
135         y=x;
136         if (z->key<x->key)
137         {
138             x=x->left;
139         }
140         else x=x->right;
141     }
142     if (y==nil)
143     {
144         root=z;
145     }
146     else if(z->key<y->key)
147     {
148         y->left=z;
149     }
150     else y->right=z;
151     z->left=nil;
152     z->right=nil;
153     z->color=RED;
154     RB_INSERT_INSERT_FIXUP(T,z);
155 }
156 //中序遍历
157 void InOderTraverse(struct Tree *p)
158 {
159     if (p!=nil)
160     {
161         InOderTraverse(p->left);
162         cout<<p->key<<" "<<p->color<<" "<<endl;
163         InOderTraverse(p->right);
164     }
165 }
166 void main()
167 {
168     nil=new struct Tree[LEN];
169     nil->key=Nil;nil->color=BLACK;
170     root=nil;
171     int i=0;
172     struct Tree*ROOT=new struct Tree[LEN];
173     cin>>ROOT->key;
174     RB_INSERT(nil,ROOT);
175     root=ROOT;
176     while (i!=12)
177     {
178         struct Tree*z=new struct Tree[LEN];
179         cin>>z->key;
180         RB_INSERT(root,z);
181         i++;
182     }
183     InOderTraverse(root);
184 }
时间: 2024-10-07 07:27:00

算法11---红黑树不带父结点指针的插入实现的相关文章

不带父结点的红黑树实现

由于只看到13.3节,所以暂时只实现旋转和插入函数. 思考:如果不带父结点,那么在需要访问z的父结点时,我们可以借助查找函数从根结点到待查找结点z的路径上必然能找到z的父结点和祖父结点,所以由此可访问父结点.不过这种方法使得旋转函数时间增加到O(lgn),而插入函数也相应的增加到O(lgnlgn).节省了空间上的内存,同时增加了运行时间. 具体代码如下: #include <iostream> using namespace std; #define BLACK 0 #define RED 1

算法之红黑树

红黑树(一) 原理和算法详细介 1 R-B Tree简介 R-B Tree,全称是Red-Black Tree,又称为"红黑树",它一种特殊的二叉查找树.红黑树的每个节点上都有存储位表示节点的颜色,可以是红(Red)或黑(Black). 红黑树的特性:(1)每个节点或者是黑色,或者是红色.(2)根节点是黑色.(3)每个叶子节点(NIL)是黑色. [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!](4)如果一个节点是红色的,则它的子节点必须是黑色的.(5)从一个节点到该节点

算法导论-------------红黑树

红黑树是一种二叉查找树,但在每个结点上增加了一个存储位表示结点的颜色,可以是RED或者BLACK.通过对任何一条从根到叶子的路径上各个着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,因而是接近平衡的.本章主要介绍了红黑树的性质.左右旋转.插入和删除.重点分析了在红黑树中插入和删除元素的过程,分情况进行详细讨论.一棵高度为h的二叉查找树可以实现任何一种基本的动态集合操作,如SEARCH.PREDECESSOR.SUCCESSOR.MIMMUM.MAXMUM.INSERT.DELETE等

算法:红黑树

算法:红黑树 红黑树介绍 红黑树(英语:Red–black tree)是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组.它是在1972年由鲁道夫·贝尔发明的,他称之为"对称二叉B树",它现代的名字是在Leo J. Guibas和Robert Sedgewick于1978年写的一篇论文中获得的. 红黑树本质上是一种二叉查找树,但它在二叉查找树的基础上额外添加了一个标记(颜色),同时具有一定的规则.这些规则使红黑树保证了一种平衡,插入.删除.查找的最坏时

算法导论 红黑树 学习 旋转(二)

学习算法 还是建议看看算法导论 算法导论第三版 如果不看数学推导 仅看伪代码 难度还是适中 本系列只是记录我的学习心得 和伪代码转化代码的过程 深入学习 还是建议大家看看算法书籍 教程更加系统. 本文参考算法导论第13章节 红黑树 代码由本人写成 转载请标明出处 红黑树是一个带颜色的二叉树 有以下5点性能 1 每个节点或者红色或者黑色 2 根节点黑色 3 每个叶子节点(nil)为黑色 4 如果一个节点是红色的则它的两个子节点都是黑色 5 每个节点 该节点到子孙节点的路径上 黑色节点数目相同 如图

算法导论 红黑树 学习 删除(四)

版权声明:本文为博主原创文章,未经博主允许不得转载.技术博客 http://blog.csdn.net/stecdeng 技术交流群 群号码:324164944 欢迎c c++ windows驱动爱好者 服务器程序员沟通交流 学习算法 还是建议看看算法导论 算法导论第三版 如果不看数学推导 仅看伪代码 难度还是适中 本系列只是记录我的学习心得 和伪代码转化代码的过程 深入学习 还是建议大家看看算法书籍 教程更加系统. 本文参考算法导论第13章节 红黑树 代码由本人写成 转载请标明出处 先看看不做

[[算法导论]红黑树速记

红黑树的性质: 1.每个结点要么是红色要么是黑色的. 2.根结点是黑色的. 3.所有叶结点(nil)是黑色的. 4.每个红色结点的两个孩子都是黑色的. 5.每个结点到其后代叶结点的简单路径上均包含相同数目的黑色结点. INSERT操作按二叉搜索树的方法插入新结点. INSERT-FIXUP(三种情况): 插入后新结点(z)为红色,当z.p==z.p.p.left时. 循环条件:父结点为红色. 情况1:叔结点(z.p.p.right)为红色. 父结点和叔结点改为黑色,祖父结点改为红色并成为新的z结

Java数据结构和算法(八)--红黑树与2-3树

红黑树规则: 1.根节点与叶节点都是黑色节点 2.每个红色节点的两个子节点都是黑色节点,反之,不做要求,换句话说就是不能有连续两个红色节点 3.从根节点到所有叶子节点上的黑色节点数量是相同的 一般对红黑树的讲述都是先给出这样的定义,这样想对不太容易理解的,而在算法4一书中,直接跳过这些规则,而讲述了红黑树与2-3树的等价性 如果我们先了解2-3树,理解了红黑树与2-3树之间的关系,回过头就会发现红黑树不难 2-3树: 2-3树满足二分搜索树的基本性质,但是不是二叉树 2-3树节点可以存放一个元素

算法导论 红黑树 实现

由于红黑树的删除用到了二叉树的一些函数 所以我们从二叉树讲起 二叉树 不带颜色的红黑树 看看两张画的有点丑的图 如图 一个节点 记录一个数值 同时还有两个指向该节点两个儿子的标识 儿子有两个 左儿子和右儿子 图中就有两个二叉树示例 一个仅有右儿子  一个左右儿子均有 C语言中或者C++语言中我们这样定义二叉树结构 struct node { std::shared_ptr<node> left_; //智能指针 std::shared_ptr<node> right_; int v