二叉排序树算法

合集下载

二叉排序树

二叉排序树

9
第9章
第三节
二、二叉排序树(插入)

查找
动态查找表
二叉排序树是一种动态查找表


当树中不存在查找的结点时,作插入操作
新插入的结点一定是叶子结点(只需改动一个 结点的指针) 该叶子结点是查找不成功时路径上访问的最后 一个结点的左孩子或右孩子(新结点值小于或 大于该结点值) 10

第9章
第三节
查找
19
在二叉排序树中查找关 键字值等于37,88,94
3
第9章
第三节
查找
动态查找表
二、二叉排序树(查找函数)中结点结构定义 二叉排序树通常采用二叉链表的形式进行存 储,其结点结构定义如下:
typedef struct BiNode { int data; BiNode *lChild, *rChild; }BiNode,*BitTree;
4
第9章
第三节
查找
动态查找表
2、二叉排序树的定义 定义二叉排序树所有用到的变量 BitTree root; int
//查找是否成功(1--成功,0--不成功) //查找位置(表示在BisCount层中的第几个位置
BisSuccess;
int
int
BisPos;
BisCount;
//查找次数(相当于树的层数)
7
第9章
第三节
查找
动态查找表
二、二叉排序树(查找函数)
else { BisSuccess = 0; root=GetNode(k);//查找不成功,插入新的结点}
} BiNode * GetNode(int k) { BiNode *s; s = new BiNode; s->data = k; s->lChild = NULL; s->rChild = NULL; return(s);}

二叉排序树

二叉排序树

②若*p结点只有左子树,或只有右子树,则可将*p的左子 树或右子树直接改为其双亲结点*f的左子树,即: f->1child=p->1child(或f->1child=p->rchild); free(p); *f
F *p P P1
*f
F
*f
F *p P
*f
F
Pr
P1
Pr
③若*p既有左子树,又有右子树。则:
-1 0
47
-1
47
47
0
31 69
69
25
0
47
0
25
0
47
-1 0
31
0
69
0
40
69
40
69
0
25 76
40
76
(a)
AL、BL、BR 都是空树
(b) AL、BL、BR 都是非空树
LR型调整操作示意图
2
A
-1
0
C
AR C BL CL CR AR
0 0
B BL CL S
B
A
CR
(a) 插入结点*s后失去平衡
31
0 0 -1
31
0 1
28
0
25
0 0
47
0
25
-1
47
0
25
0
31
0
16 0
28
16
28
0
16 30
30
47
(c) LR(R)型调整
RL型调整操作示意图
A B C A BR CR B BR
AL
C
AL
CL CR

数据结构 二叉排序树

数据结构 二叉排序树

9.6.2 哈希函数的构造方法
构造哈希函数的目标:
哈希地址尽可能均匀分布在表空间上——均 匀性好; 哈希地址计算尽量简单。
考虑因素:
函数的复杂度; 关键字长度与表长的关系; 关键字分布情况; 元素的查找频率。
一、直接地址法 取关键字或关键字的某个线性函数值为哈希地址 即: H(key) = key 或: H(key) = a* key + b 其中,a, b为常数。 例:1949年后出生的人口调查表,关键字是年份 年份 1949 1950 1951 … 人数 … … … …
9.4 二叉排序树
1.定义:
二叉排序树(二叉搜索树或二叉查找树) 或者是一棵空树;或者是具有如下特性的二叉树
(1) 若它的左子树不空,则左子树上所有结点的 值均小于根结点的值;
(2) 若它的右子树不空,则右子树上所有结点 的值均大于等于根结点的值; (3) 它的左、右子树也都分别是二叉排序树。
例如:
H(key)
通常设定一个一维数组空间存储记录集合,则 H(key)指示数组中的下标。
称这个一维数组为哈希(Hash)表或散列表。 称映射函数 H 为哈希函数。 H(key)为哈希地址
例:假定一个线性表为: A = (18,75,60,43,54,90,46) 假定选取的哈希函数为
hash3(key) = key % 13
H(key) = key + (-1948) 此法仅适合于: 地址集合的大小 = = 关键字集合的大小
二、数字分析法
假设关键字集合中的每个关键字都是由 s 位数 字组成 (u1, u2, …, us),分析关键字集中的全体, 并从中提取分布均匀的若干位或它们的组合作为 地址。 例如:有若干记录,关键字为 8 位十进制数, 假设哈希表的表长为100, 对关键字进行分析, 取随机性较好的两位十进制数作为哈希地址。

二叉排序树

二叉排序树

二叉排序树1.二叉排序树定义二叉排序树(Binary Sort Tree)或者是一棵空树;或者是具有下列性质的二叉树:(1)若左子树不空,则左子树上所有结点的值均小于根结点的值;若右子树不空,则右子树上所有结点的值均大于根结点的值。

(2)左右子树也都是二叉排序树,如图6-2所示。

2.二叉排序树的查找过程由其定义可见,二叉排序树的查找过程为:(1)若查找树为空,查找失败。

(2)查找树非空,将给定值key与查找树的根结点关键码比较。

(3)若相等,查找成功,结束查找过程,否则:①当给值key小于根结点关键码,查找将在以左孩子为根的子树上继续进行,转(1)。

②当给值key大于根结点关键码,查找将在以右孩子为根的子树上继续进行,转(1)。

3.二叉排序树插入操作和构造一棵二叉排序树向二叉排序树中插入一个结点的过程:设待插入结点的关键码为key,为将其插入,先要在二叉排序树中进行查找,若查找成功,按二叉排序树定义,该插入结点已存在,不用插入;查找不成功时,则插入之。

因此,新插入结点一定是作为叶子结点添加上去的。

构造一棵二叉排序树则是逐个插入结点的过程。

对于关键码序列为:{63,90,70,55,67,42,98,83,10,45,58},则构造一棵二叉排序树的过程如图6-3所示。

4.二叉排序树删除操作从二叉排序树中删除一个结点之后,要求其仍能保持二叉排序树的特性。

设待删结点为*p(p为指向待删结点的指针),其双亲结点为*f,删除可以分三种情况,如图6-4所示。

(1)*p结点为叶结点,由于删去叶结点后不影响整棵树的特性,所以,只需将被删结点的双亲结点相应指针域改为空指针,如图6-4(a)所示。

(2)*p结点只有右子树或只有左子树,此时,只需将或替换*f结点的*p子树即可,如图6-4(b)、(c)所示。

(3)*p结点既有左子树又有右子树,可按中序遍历保持有序地进行调整,如图6-4(d)、(e)所示。

设删除*p结点前,中序遍历序列为:① P为F的左子女时有:…,Pi子树,P,Pj,S子树,Pk,Sk子树,…,P2,S2子树,P1,S1子树,F,…。

数据结构之二叉树(BinaryTree)

数据结构之二叉树(BinaryTree)

数据结构之⼆叉树(BinaryTree)⽬录导读 ⼆叉树是⼀种很常见的数据结构,但要注意的是,⼆叉树并不是树的特殊情况,⼆叉树与树是两种不⼀样的数据结构。

⽬录 ⼀、⼆叉树的定义 ⼆、⼆叉树为何不是特殊的树 三、⼆叉树的五种基本形态 四、⼆叉树相关术语 五、⼆叉树的主要性质(6个) 六、⼆叉树的存储结构(2种) 七、⼆叉树的遍历算法(4种) ⼋、⼆叉树的基本应⽤:⼆叉排序树、平衡⼆叉树、赫夫曼树及赫夫曼编码⼀、⼆叉树的定义 如果你知道树的定义(有限个结点组成的具有层次关系的集合),那么就很好理解⼆叉树了。

定义:⼆叉树是n(n≥0)个结点的有限集,⼆叉树是每个结点最多有两个⼦树的树结构,它由⼀个根结点及左⼦树和右⼦树组成。

(这⾥的左⼦树和右⼦树也是⼆叉树)。

值得注意的是,⼆叉树和“度⾄多为2的有序树”⼏乎⼀样,但,⼆叉树不是树的特殊情形。

具体分析如下⼆、⼆叉树为何不是特殊的树 1、⼆叉树与⽆序树不同 ⼆叉树的⼦树有左右之分,不能颠倒。

⽆序树的⼦树⽆左右之分。

2、⼆叉树与有序树也不同(关键) 当有序树有两个⼦树时,确实可以看做⼀颗⼆叉树,但当只有⼀个⼦树时,就没有了左右之分,如图所⽰:三、⼆叉树的五种基本状态四、⼆叉树相关术语是满⼆叉树;⽽国际定义为,不存在度为1的结点,即结点的度要么为2要么为0,这样的⼆叉树就称为满⼆叉树。

这两种概念完全不同,既然在国内,我们就默认第⼀种定义就好)。

完全⼆叉树:如果将⼀颗深度为K的⼆叉树按从上到下、从左到右的顺序进⾏编号,如果各结点的编号与深度为K的满⼆叉树相同位置的编号完全对应,那么这就是⼀颗完全⼆叉树。

如图所⽰:五、⼆叉树的主要性质 ⼆叉树的性质是基于它的结构⽽得来的,这些性质不必死记,使⽤到再查询或者⾃⼰根据⼆叉树结构进⾏推理即可。

性质1:⾮空⼆叉树的叶⼦结点数等于双分⽀结点数加1。

证明:设⼆叉树的叶⼦结点数为X,单分⽀结点数为Y,双分⽀结点数为Z。

二叉排序树

二叉排序树

就维护表的有序性而言,二叉排序树无须移 动结点,只需修改指针即可完成插入和删 除操作,且其平均的执行时间均为O(lgn), 因此更有效。二分查找所涉及的有序表是 一个向量,若有插入和删除结点的操作, 则维护表的有序性所花的代价是O(n)。当 有序表是静态查找表时,宜用向量作为其 存储结构,而采用二分查找实现其查找操 作;若有序表里动态查找表,则应选择二 叉排序树作为其存储结构。
if(q->lchild) //*q的左子树非空,找*q的左子 树的最右节点r. {for(q=q->lchild;q->rchild;q=q->rchild); q->rchild=p->rchild; } if(parent->lchild==p)parent->lchild=p>lchild; else parent->rchild=p->lchild; free(p); /释放*p占用的空间 } //DelBSTNode
下图(a)所示的树,是按如下插入次序构成的: 45,24,55,12,37,53,60,28,40,70 下图(b)所示的树,是按如下插入次序构成的: 12,24,28,37,40,45,53,55,60,70
在二叉排序树上进行查找时的平均查找长度和二叉树的形态 有关: ①在最坏情况下,二叉排序树是通过把一个有序表的n 个结点依次插入而生成的,此时所得的二叉排序树蜕化为 棵深度为n的单支树,它的平均查找长度和单链表上的顺 序查找相同,亦是(n+1)/2。 ②在最好情况下,二叉排序树在生成的过程中,树的形 态比较匀称,最终得到的是一棵形态与二分查找的判定树 相似的二叉排序树,此时它的平均查找长度大约是lgn。 ③插入、删除和查找算法的时间复杂度均为O(lgn)。 (3)二叉排序树和二分查找的比较 就平均时间性能而言,二叉排序树上的查找和二分查找 差不多。

平衡二叉树

平衡二叉树
#define EH 0 //等高
#define RH -1 //右高
//平衡二叉树的类型
struct AVLNode
{
int data;
int bf; //bf结点的平衡因子,只能够取0,-1,1,为左子树的深度减去右子树的深度
struct AVLNode *lchild,*rchild; //左、右孩子指针
{
AVLNode *rc,*rd;
rc=T->rchild;
switch(rc->bf)
{
case RH:
T->bf=rc->bf=EH;
L_Rotate(T);
break;
case LH:
rd=rc->lchild;
switch(rd->bf)
{
case RH:
T->bf=LH;
rc->bf=EH;
};
2.右旋操作:
void R_Rotate(AVLNode *&p)//LL型算法
{
AVLNode *lc=p->lchild; // lc指向p的左子树根结点
p->lchild=lc->rchild; // lc的右子树挂接为p(之前跟节点)的左子树
lc->rchild=p;
p=lc; // p指向新的根结点
插入和删除:
插入删除是互为镜像的操作。我们可以采用前面对二叉排序树的删除操作来进行。然后,在删除掉结点后,再对平衡树进行平衡化处理。删除之所以删除操作需要的平衡化可能比插入时次数多,就是因为平衡化不会增加子树的高度,但是可能会减少子树的高度,在有有可能使树增高的插入操作中,一次平衡化能抵消掉增高;在有可能使树减低的删除操作中,平衡化可能会带来祖先节点的不平衡。AVL树体现了一种平衡的美感,两种旋转是互为镜像的,插入删除是互为镜像的操作,没理由会有那么大的差别。实际上,平衡化可以统一的这样来操作:

数据结构二叉排序树

数据结构二叉排序树

05
13
19
21
37
56
64
75
80
88
92
low mid high 因为r[mid].key<k,所以向右找,令low:=mid+1=4 (3) low=4;high=5;mid=(4+5) div 2=4
05
13
19
low
21
37
56
64
75
80
88
92
mid high
因为r[mid].key=k,查找成功,所查元素在表中的序号为mid 的值
平均查找长度:为确定某元素在表中某位置所进行的比 较次数的期望值。 在长度为n的表中找某一元素,查找成功的平均查找长度:
ASL=∑PiCi
Pi :为查找表中第i个元素的概率 Ci :为查到表中第i个元素时已经进行的比较次数
在顺序查找时, Ci取决于所查元素在表中的位置, Ci =i,设每个元素的查找概率相等,即Pi=1/n,则:
RL型的第一次旋转(顺时针) 以 53 为轴心,把 37 从 53 的左上转到 53 的左下,使得 53 的左 是 37 ;右是 90 ,原 53 的左变成了 37 的右。 RL型的第二次旋转(逆时针)
一般情况下,假设由于二叉排序树上插入结点而失去 平衡的最小子树的根结点指针为a(即a是离插入结点最 近,且平衡因子绝对值超过1的祖先结点),则失去平衡 后进行调整的规律可归纳为下列四种情况: ⒈RR型平衡旋转: a -2 b -1 h-1 a1
2.查找关键字k=85 的情况 (1) low=1;high=11;mid=(1+11) / 2=6
05
13
19
21
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

沈阳航空航天大学课程设计报告课程设计名称:数据结构课程设计课程设计题目:二叉排序树算法院(系):计算机学院专业:计算机科学与技术班级:04010103学号:2010040101097姓名:郭胜龙指导教师:丁一军此页为任务书目录1 课程设计介绍 (1)1.1课程设计内容 (1)1.2课程设计要求 (1)2 课程设计原理 (2)2.1课设题目粗略分析 (2)2.2原理图介绍 (2)2.2.1 功能模块图 (2)2.2.2 main(主函数) (2)2.2.3 SearchBST(查找) (3)2.2.4 InsertBST(插入) (4)2.2.5 CreatBST(建立) (4)2.2.6 DeleteBST(删除) (4)2.2.7 PreOrder(先序遍历) (5)2.2.8 InOrder(中序遍历) (5)3 数据结构分析 (7)3.1存储结构 (7)3.2算法描述 (7)4 调试与分析 (12)4.1调试过程 (12)4.2程序执行过程 (12)参考文献 (15)附录(关键部分程序清单) (16)沈阳航空航天大学课程设计报告1 课程设计介绍1.1 课程设计内容题目内容:1.构造二叉排序树;2.输出该二叉排序树的先序、中序遍历序列;3.删除该二叉排序树的任意一个结点;4.输出删除后的二叉排序树的先序、中序遍历序列。

1.2课程设计要求题目要求:1.按要求建立不同的二叉排序树;2.数据自定3.独立完成课程设计任务2 课程设计原理2.1课设题目粗略分析根据课设题目要求,拟将整体程序分为七大模块。

以下是七个模块的大体分析:main ():主函数模块SearchBST ():查找相应的结点 InsertBST1():插入一个新的结点 CreatBST ():创建一棵二叉排序树 DeleteNode ():删除结点PreOrder ()对二叉排序树进行先序遍历 InOrder ()对二叉排序树进行中序遍历2.2 原理图介绍2.2.1 功能模块图图2.2.1 功能模块结构图2.2.2 main (主函数)功能:连接各个函数,确定他们的执行顺序和条件。

二叉排序树算法主模块查找模块 插入模块 建立模块 删除模块 先序遍历模块 中序遍历模块图2.2.2主函数流程图2.2.3 SearchBST (查找)功能:查找相应的结点。

图2.2.3 查找操作的流程图开始选择功能Choose=1 建立二叉排序树Choose=2 删除x 结点Choose=3 先序遍历二叉排Choose=0 退出Choose=4 中序遍历二叉排A结束AYY开始T->data==key s=TT->data>keys=SearchBST(T->rchild)s=SearchBST(T->lchild)NN返回s结束2.2.4 InsertBST (插入)功能:插入一个新的结点。

图2.2.4 插入操作的流程图2.2.5 CreatBST (建立)功能:建立一个已知数据的二叉排序树。

图2.2.5 建立操作的流程图2.2.6 DeleteBST (删除)功能:删除值为x 的结点。

YY开始T==NULL T=ss->data>T->datas=InserBST(T->rchild)s=InsertBST(T->lchild)NN结束开始输入结点数n调用插入函数结束开始调用查找函数删除p结点右子树连在左子树上左子树连在p结点的父母节点上结束图2.2.6 删除操作的流程图2.2.7 PreOrder(先序遍历)功能:对二叉排序树进行先序遍历,并输出序列。

开始访问TPreOrder(T->rchild)PreOrder(T->lchild)结束图2.2.7 先序遍历的流程图2.2.8 InOrder(中序遍历)功能:对二叉排序树进行先序遍历,并输出序列。

开始InOrder(T->rchild)访问TInOrder(T->lchild)结束图2.2.8 中序遍历的流程图沈阳航空航天大学课程设计报告错误!未指定书签。

3 数据结构分析3.1 存储结构定义一个链表式的二叉排序树,用链表的方式构造结点,存储二叉排序树中的结点、结点类型和指针类型如下:typedef struct BiTNode{int data;struct BiTNode *lchild,*rchild;}BiTNode,*BiTree;3.2 算法描述1、二叉排序树的查找算法(1)若二叉排序树为空,则查找失败。

(2)否则,将根结点的关键字与待查关键字进行比较,若相等,则查找成功;若根节点关键字大于待查值,则进入左子树重复次步骤,否则,进入右子树进行此步骤;若在查找过程中遇到二叉排序树的叶子节点时,还没有找到待查节点,则查找不成功。

算法如下:BiTree SearchBST1(BiTree T, int key){//在根指针T所指二叉排序树中递归查找关键字等于 key 的数据元素//若成功,返回指向该数据元素结点的指针,否则返回空指针;s为返回 //指针BiTree s;if(T==NULL) return NULL;else if(T->data==key) s=T;else if(T->data>key) //key大于当前结点的关键字,则查找左子树s=SearchBST1(T->lchild,key);else//key小于当前结点的关键字则查找右子树s=SearchBST1(T->rchild,key);return s;}3、二叉排序树的节点插入算法在二叉排序树中插入一个新节点,首先要查找该节点在二叉排序树中是否已经存在。

若二叉排序树中不存在关键字等于x的节点,则插入。

将一个关键字值为x的节点s插入到二叉排序树中,可以用下面的方法:(1)若二叉排序树为空,则关键字为x的节点s成为二叉排序树的根(2)若二叉排序树非空,则将x与二叉排序树根进行比较,如果x的值等于根节点关键值,则停止插入;如果x的根节点值小于根节点关键值,则将x插入左子树;如果x的值大于根节点关键字的值,则将x插入右子树。

在左右两个子树的插入方法与整个二叉排序树相同。

算法如下:void InsertBST1(BiTree &T,BiTNode *s){//在二叉树排序树T中,插入一个结点s的递归算法BiTree t;t=SearchBST1(T,s->data);//若s的关键字不在T中出现,则插入if(!t){if(T==NULL)T=s; //空树时作为根结点else if(s->data<T->data)InsertBST1(T->lchild,s); //将s插入T的左子树 elseInsertBST1(T->rchild,s); //将s插入T的右子树}}3、二叉排序树的节点删除算法在二叉排序树中删除节点,首先要进行查找操作,以确定被删除的节点是否在二叉排序树中若不在,则不做任何操作;否则,假设要删除的节点为*p,节点*p的父节点为*f,并假设*p是*f的左孩子。

根据被删除节点*p有无孩子,删除部分可做以下3中情况讨论:(1)若*p为叶子节点,则可令其父节点*f的左孩子指针域为空,直接将其删除。

(2)若*p节点只有右子树或左子树,则可以将p的左子树或右子树直接改为其双亲节点f的左子树。

(3)若*p既有左子树又有右子树;将节点*s为*p的中序前驱。

首先找到*p 的中序前驱节点*s,然后用节点*s的值代替节点*p的值,再将节点*s删除,节点*s的原左子树改为*s的双亲节点*q的右子树;算法如下:DeleteNode(BiTree &T, int x){//从二叉树排序树T中删除任意结点,其关键字为xBiTree p,q,pParent,pChileNode;p=T; //从根结点开始查找pParent = NULL;// T的双亲为NULLwhile (p)// 开始查找关键字为x的结点p,及双亲pParent{if (x == p->data)break;pParent = p;p = x > p->data ? p->rchild : p->lchild;}if (p==NULL){printf("要删除的结点不存在\n");return false;} // 至此已找到目标结点p// pChileNode = p存在的孩子或NULL,左右都存在时,取左pChileNode = p->lchild!= NULL ? p->lchild : p->rchild;if(p->lchild==NULL||p->lchild==NULL){if (pParent == NULL)T= pChileNode;else{if(p==pParent->lchild)pParent->lchild= pChileNode;elsepParent->rchild = pChileNode;}free(p);//释放空间} // 当2个孩子都存在时else{//pChileNode已指向p->lchildq=p;while (pChileNode->rchild){//在p的左字树中查找中序p的前驱pChileNode,q为其双亲 q=pChileNode;pChileNode = pChileNode->rchild;}p->data=pChileNode->data;//p的前驱pChileNodede 的关键值赋给pif(q!=p) //将删除p转化为删除pChileNodede(最多只有左字树)结点{q->rchild=pChileNode->lchild;//p的左字树有右孩子 }else{q->lchild=pChileNode->lchild;//p的左字树有右孩子 }free(pChileNode);}return true;}4 调试与分析4.1 调试过程在调试程序是主要遇到以下几类问题:1.二叉树的存储结构的选择2.界面函数的调整3.删除的时候二叉树的调整4.2 程序执行过程执行过程如下图:图4.2.1 界面图图4.2.2 建立二叉排序树图4.2.3 先序遍历序列图4.2.4 中序遍历序列图4.2.5 删除结点图4.2.6 删除后的先序遍历序列图4.2.7 删除后的中序遍历序列沈阳航空航天大学课程设计报告错误!未指定书签。

参考文献[1] 殷人昆,等. 数据结构(用面向对象方法与C++描述)[M]. 北京:清华大学出版社,2002.[2] 宁正元,等. 算法与数据结构习题精解和实验指导[M]. 北京:清华大学出版社,2002.[3] 严蔚敏,吴伟民.数据结构[M].北京:清华大学出版社,2007.[4] 张长海,陈娟.C程序设计[M].北京:高等教育出版社,2004.[5] 谭浩强.C程序设计[M].北京:清华大学出版社,2005.附录(关键部分程序清单)#include <stdio.h>#include <malloc.h>#include <stdlib.h>typedef struct BiTNode{int data;struct BiTNode *lchild,*rchild;}BiTNode,*BiTree;/************************查找**************************/BiTree SearchBST1(BiTree T, int key){//在根指针T所指二叉排序树中递归查找关键字等于 key 的数据元素//若成功,返回指向该数据元素结点的指针,否则返回空指针;s为返回 //指针BiTree s;if(T==NULL) return NULL;else if(T->data==key) s=T;else if(T->data>key) //key大于当前结点的关键字,则查找左子树s=SearchBST1(T->lchild,key);else//key小于当前结点的关键字则查找右子树s=SearchBST1(T->rchild,key);return s;}/************************插入**************************/void InsertBST1(BiTree &T,BiTNode *s){//在二叉树排序树T中,插入一个结点s的递归算法BiTree t;t=SearchBST1(T,s->data);//若s的关键字不在T中出现,则插入if(!t){if(T==NULL)T=s; //空树时作为根结点else if(s->data<T->data)InsertBST1(T->lchild,s); //将s插入T的左子树elseInsertBST1(T->rchild,s); //将s插入T的右子树}}/***********************建立****************************/BiTree CreatBST(int n){//建立n个关键字的二叉排序树,//从键盘输入调建立n个关键字依次用InsertBST1(插入函数),//返回根结点TBiTree T,s;int i,key;T=NULL;printf("建树过程:\n");for(i=1;i<=n;i++){printf("插入结点关键值:\n");scanf("%d",&key);s=(BiTree)malloc(sizeof(BiTNode));//开辟存储单元,并对结点赋值s->data=key;s->lchild=NULL; s->rchild=NULL;InsertBST1(T,s); //调用插入算法}return T;}/***********************删除*****************************/ DeleteNode(BiTree &T, int x){//从二叉树排序树T中删除任意结点,其关键字为xBiTree p,q,pParent,pChileNode;p=T; //从根结点开始查找pParent = NULL;// T的双亲为NULLwhile (p)// 开始查找关键字为x的结点p,及双亲pParent{if (x == p->data)break;pParent = p;p = x > p->data ? p->rchild : p->lchild;}if (p==NULL){printf("要删除的结点不存在\n");return false;} // 至此已找到目标结点p// pChileNode = p存在的孩子或NULL,左右都存在时,取左pChileNode = p->lchild!= NULL ? p->lchild : p->rchild;if(p->lchild==NULL||p->lchild==NULL){if (pParent == NULL)T= pChileNode;else{if(p==pParent->lchild)pParent->lchild= pChileNode;elsepParent->rchild = pChileNode;}free(p);//释放空间} // 当2个孩子都存在时else{//pChileNode已指向p->lchildq=p;while (pChileNode->rchild){//在p的左字树中查找中序p的前驱pChileNode,q为其双亲 q=pChileNode;pChileNode = pChileNode->rchild;}p->data=pChileNode->data;//p的前驱pChileNodede 的关键值赋给p if(q!=p) //将删除p转化为删除pChileNodede(最多只有左字树)结点 {q->rchild=pChileNode->lchild;//p的左字树有右孩子 }else{q->lchild=pChileNode->lchild;//p的左字树有右孩子 }free(pChileNode);}return true;}/**********************先序遍历************************/void PreOrder(BiTree T){if(T!=NULL){printf("%3d",T->data);PreOrder(T->lchild);PreOrder(T->rchild);}}/*********************中序遍历**************************/void InOrder(BiTree T){if(T!=NULL){InOrder(T->lchild);printf("%3d",T->data);InOrder(T->rchild);}}/*********************主函数******************************/void main(){int n,x,choose;BiTree T;while(1){printf("\n\n*******************************************\n"); printf("************************************\n");printf("二叉排序树算法\n");printf("************************************\n"); printf("请选择操作:\n");printf("0.退出\n");printf("1.建立一棵二叉排序树\n");printf("2.删除一个任意结点\n");printf("3.先序遍历序列\n");printf("4.中序遍历序列\n");printf("Please choose:");scanf("%d",&choose);switch(choose){case 1:system("cls");printf("输入结点个数n=:\n");scanf("%d",&n);T=CreatBST(n);system("cls");break;case 2:system("cls");printf("输入想要删除的结点x=:\n"); scanf("%d",&x);DeleteNode(T, x);system("cls");break;case 3:system("cls");printf("先序遍历序列:\n");PreOrder(T);printf("\n");break;case 4:system("cls");printf("中序遍历序列:\n");InOrder(T);printf("\n");break;default:exit(0);}}}沈阳航空航天大学课程设计报告课程设计总结:指导教师评语:指导教师(签字):年月日课程设计成绩。

相关文档
最新文档