二叉树操作课程设计报告

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

二叉树操作课程设计报告

一、总体设计

1、程序功能简介

带枚举值的二叉树的实现,利用枚举值使二叉树的组成尽量平衡,即左右子树的级数相差不多。可以完成二叉树结点数据的插入、删除、查找和输出等功能。

2、程序设计要求

(1)仔细阅读程序,回答下列问题

a.枚举值Red和Black在程序中起什么作用,Red的结点和Black的结点有什么区别?

b.一个结点的左右子树最多可以相差几级?为什么?

c.程序是通过哪些函数来调整二叉树左右子树的结构,举例说明如何调整。

(2)增加对二叉树上结点中的数据进行由大到小排序的函数。(3)增加对二叉树上结点中的数据进行由小到大排序的函数。(4)增加计算二叉树中结点上数据的平均值的函数。

(5)修改main函数,增加菜单选项,使得用户可以通过键盘反复输入命令或数值查看运行结果。

评定难易等级:A级

二、详细设计

1、对二叉树的初步了解

(1)本题中的二叉树是一颗二叉查找树,首先应具有二叉查找树的

特征。它或者是一棵空树;或者是具有下列性质的二叉树:若左子树不空,则左子树上所有结点的值均小于它的根结点的值;若右子树不空,则右子树上所有结点的值均大于它的根结点的值;左、右子树也分别为二叉排序树。且结点上数据互不相同。如图所示:

(2)本题中的二叉树同时为平衡二叉树中的一类——红黑树,因此它具有红黑树的特征。

红黑树是每个节点都带有颜色属性的二叉查找树,颜色或红色或黑色。在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求:

性质1. 节点是红色或黑色。

性质2. 根节点是黑色。

性质3 每个叶节点是黑色的。

性质4 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)

性质5. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色

节点。

这些约束强制了红黑树的关键性质: 从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。要知道为什么这些特性确保了这个结果,注意到性质4导致了路径不能有两个毗连的红色节点就足够了。最短的可能路径都是黑色节点,最长的可能路径有交替的红色和黑色节点。因为根据性质5所有最长的路径都有相同数目的黑色节点,这就表明了没有路径能多于任何其他路径的两倍长。

(3)由于红黑树性质的约束,在红黑树上只读操作不需要对用于二叉查找树的操作做出修改,因为它也是二叉查找树。但是,在插入和删除之后,红黑属性可能变得违规。恢复红黑属性需要少量(O(log n))的颜色变更(这在实践中是非常快速的)并且不超过三次树旋转(对于插入是两次)。这允许插入和删除保持为O(log n) 次,但是它导致了非常复杂的操作。

插入

我们首先以二叉查找树的方法增加节点并标记它为红色。(如果设为黑色,就会导致根到叶子的路径上有一条路上,多一个额外的黑节点,这个是很难调整的。但是设为红色节点后,可能会导致出现两个连续红色节点的冲突,那么可以通过颜色调换(color flips)和树旋转来调整。)下面要进行什么操作取决于其他临近节点的颜色。同人类的家族树中一样,我们将使用术语叔父节点来指一个节点的父节点的兄弟节点。注意:

性质1和性质3总是保持着。

性质4只在增加红色节点、重绘黑色节点为红色,或做旋转时受到威胁。

性质5只在增加黑色节点、重绘红色节点为黑色,或做旋转时受到威胁。

在下面的示意图中,将要插入的节点标为N ,N 的父节点标为P ,N 的祖父节点标为G ,N 的叔父节点标为U 。在图中展示的任何颜色要么是由它所处情形所作的假定,要么是这些假定所暗含 (imply) 的。 int RBtree::NodeInsert(RBnode *x)

{ RBnode *tmp1=ROOT,*tmp2=tmp1;

if(ROOT==NIL) { ROOT=x;

x ->left=x ->right=x ->p=NIL;

++alive;

return 0;

}

while((tmp1!=NIL)&&(tmp1->value!=x ->value)) { tmp2=tmp1;

tmp1=x ->value>tmp1->value?tmp1- }

if(tmp1==NIL)

{ if(x ->value>tmp2->value) tmp2->right=x;

else

tmp2->left=x;

x->p=tmp2;

x->left=x->right=NIL;

++alive;

return 0;

}

return 1;

}

void RBtree::Insert(const T&val)

{ RBnode *x=new RBnode(val),*y; 用数值生成新结点if(NodeInsert(x)==1)

{ cout<

return;

}

while((x!=ROOT)&&(x->p->color==Red)) {

if(x->p==x->p->p->left)

{ y=x->p->p->right;

if(y->color==Red)

{ x->p->color=Black;

y->color=Black;情形3: 如果父节点P和叔父节点U二者都是红色,则我们可以将它们两个重绘为黑色并重绘祖父节点G为红色(用来保持性质5)。现在我们的新节点N有了一个黑色的父节点P。因为通过父节点P或叔父节点U的任何路径都必定通过祖父节点G,在这些路径上的黑节点数目没有改变。

相关文档
最新文档