数据结构 建立二叉排序树
数据结构c语言课设-二叉树排序
题目:二叉排序树的实现1 内容和要求1)编程实现二叉排序树,包括生成、插入,删除;2)对二叉排序树进展先根、中根、和后根非递归遍历;3)每次对树的修改操作和遍历操作的显示结果都需要在屏幕上用树的形状表示出来。
4)分别用二叉排序树和数组去存储一个班(50 人以上)的成员信息(至少包括学号、姓名、成绩3 项),比照查找效率,并说明在什么情况下二叉排序树效率高,为什么?2 解决方案和关键代码2.1 解决方案:先实现二叉排序树的生成、插入、删除,编写DisplayBST函数把遍历结果用树的形状表示出来。
前中后根遍历需要用到栈的数据构造,分模块编写栈与遍历代码。
要求比照二叉排序树和数组的查找效率,首先建立一个数组存储一个班的成员信息,分别用二叉树和数组查找,利用clock〔〕函数记录查找时间来比照查找效率。
2.2关键代码树的根本构造定义及根本函数typedef struct{KeyType key;} ElemType;typedef struct BiTNode//定义链表{ElemType data;struct BiTNode *lchild, *rchild;}BiTNode, *BiTree, *SElemType;//销毁树int DestroyBiTree(BiTree &T){if (T != NULL)free(T);return 0;}//清空树int ClearBiTree(BiTree &T){if (T != NULL){T->lchild = NULL;T->rchild = NULL;T = NULL;}return 0;}//查找关键字,指针p返回int SearchBST(BiTree T, KeyType key, BiTree f, BiTree &p) {if (!T){p = f;return FALSE;}else if EQ(key, T->data.key){p = T;return TRUE;}else if LT(key, T->data.key)return SearchBST(T->lchild, key, T, p);elsereturn SearchBST(T->rchild, key, T, p);}二叉树的生成、插入,删除生成void CreateBST(BiTree &BT, BiTree p){int i;ElemType k;printf("请输入元素值以创立排序二叉树:\n");scanf_s("%d", &k.key);for (i = 0; k.key != NULL; i++){//判断是否重复if (!SearchBST(BT, k.key, NULL, p)){InsertBST(BT, k);scanf_s("%d", &k.key);}else{printf("输入数据重复!\n");return;}}}插入int InsertBST(BiTree &T, ElemType e){BiTree s, p;if (!SearchBST(T, e.key, NULL, p)){s = (BiTree)malloc(sizeof(BiTNode));s->data = e;s->lchild = s->rchild = NULL;if (!p)T = s;else if LT(e.key, p->data.key)p->lchild = s;elsep->rchild = s;return TRUE;}else return FALSE;}删除//某个节点元素的删除int DeleteEle(BiTree &p){BiTree q, s;if (!p->rchild) //右子树为空{q = p;p = p->lchild;free(q);}else if (!p->lchild) //左子树为空{q = p;p = p->rchild;free(q);}else{q = p;s = p->lchild;while (s->rchild){q = s;s = s->rchild;}p->data = s->data;if (q != p)q->rchild = s->lchild;elseq->lchild = s->lchild;delete s;}return TRUE;}//整棵树的删除int DeleteBST(BiTree &T, KeyType key) //实现二叉排序树的删除操作{if (!T){return FALSE;}else{if (EQ(key, T->data.key)) //是否相等return DeleteEle(T);else if (LT(key, T->data.key)) //是否小于return DeleteBST(T->lchild, key);elsereturn DeleteBST(T->rchild, key);}return 0;}二叉树的前中后根遍历栈的定义typedef struct{SElemType *base;SElemType *top;int stacksize;}SqStack;int InitStack(SqStack &S) //构造空栈{S.base = (SElemType*)malloc(STACK_INIT_SIZE *sizeof(SElemType));if (!S.base) exit(OVERFLOW);S.top = S.base;S.stacksize = STACK_INIT_SIZE;return OK;}//InitStackint Push(SqStack &S, SElemType e) //插入元素e为新栈顶{if (S.top - S.base >= S.stacksize){S.base = (SElemType*)realloc(S.base, (S.stacksize + STACKINCREMENT)*sizeof(SElemType));if (!S.base) exit(OVERFLOW);S.top = S.base + S.stacksize;S.stacksize += STACKINCREMENT;}*S.top++ = e;return OK;}//Pushint Pop(SqStack &S, SElemType &e) //删除栈顶,应用e返回其值{if (S.top == S.base) return ERROR;e = *--S.top;return OK;}//Popint StackEmpty(SqStack S) //判断是否为空栈{if (S.base == S.top) return TRUE;return FALSE;}先根遍历int PreOrderTraverse(BiTree T, int(*Visit)(ElemType e)) {SqStack S;BiTree p;InitStack(S);p = T;while (p || !StackEmpty(S)){if (p){Push(S, p);if (!Visit(p->data)) return ERROR;p = p->lchild;}else{Pop(S, p);p = p->rchild;}}return OK;}中根遍历int InOrderTraverse(BiTree T, int(*Visit)(ElemType e)) {SqStack S;BiTree p;InitStack(S);p = T;while (p || !StackEmpty(S)){if (p){Push(S, p);p = p->lchild;}else{Pop(S, p);if (!Visit(p->data)) return ERROR;p = p->rchild;}}return OK;}后根遍历int PostOrderTraverse(BiTree T, int(*Visit)(ElemType e)) {SqStack S, SS;BiTree p;InitStack(S);InitStack(SS);p = T;while (p || !StackEmpty(S)){if (p){Push(S, p);Push(SS, p);p = p->rchild;}else{if (!StackEmpty(S)){Pop(S, p);p = p->lchild;}}}while (!StackEmpty(SS)){Pop(SS, p);if (!Visit(p->data)) return ERROR;}return OK;}利用数组存储一个班学生信息ElemType a[] = { 51, "陈继真", 88,82, "黄景元", 89,53, "贾成", 88,44, "呼颜", 90,25, "鲁修德", 88,56, "须成", 88,47, "孙祥", 87, 38, "柏有患", 89, 9, " 革高", 89, 10, "考鬲", 87, 31, "李燧", 86, 12, "夏祥", 89, 53, "余惠", 84, 4, "鲁芝", 90, 75, "黄丙庆", 88, 16, "李应", 89, 87, "杨志", 86, 18, "李逵", 89, 9, "阮小五", 85, 20, "史进", 88, 21, "秦明", 88, 82, "杨雄", 89, 23, "刘唐", 85, 64, "武松", 88, 25, "李俊", 88, 86, "卢俊义", 88, 27, "华荣", 87, 28, "杨胜", 88, 29, "林冲", 89, 70, "李跃", 85, 31, "蓝虎", 90, 32, "宋禄", 84, 73, "鲁智深", 89, 34, "关斌", 90, 55, "龚成", 87, 36, "黄乌", 87, 57, "孔道灵", 87, 38, "张焕", 84, 59, "李信", 88, 30, "徐山", 83, 41, "秦祥", 85, 42, "葛公", 85, 23, "武衍公", 87, 94, "范斌", 83, 45, "黄乌", 60, 67, "叶景昌", 99, 7, "焦龙", 89, 78, "星姚烨", 85, 49, "孙吉", 90, 60, "陈梦庚", 95,};数组查询函数void ArraySearch(ElemType a[], int key, int length){int i;for (i = 0; i <= length; i++){if (key == a[i].key){cout << "学号:" << a[i].key << " 姓名:" << a[i].name << " 成绩:" << a[i].grade << endl;break;}}}二叉树查询函数上文二叉树根本函数中的SearchBST()即为二叉树查询函数。
《数据结构》实验指导书
1.单链表的类型定义
#include <stdio.h>
typedef int ElemType;//单链表结点类型
typedef struct LNode
{ElemType data;
struct LNode *next;
2.明确栈、队列均是特殊的线性表。
3.栈、队列的算法是后续实验的基础(广义表、树、图、查找、排序等)。
六、实验报告
根据实验情况和结果撰写并递交实验报告。
实验四 串
一、预备知识
1.字符串的基本概念
2.字符串的模式匹配算法
二、实验目的
1.理解字符串的模式匹配算法(包括KMP算法)
typedef struct
{ElemType *base;
int front,rear;
} SqQueue;
4.单链队列的类型定义
typedef struct QNode
{QElemType data;
typedef struct list
{ElemType elem[MAXSIZE];//静态线性表
int length; //顺序表的实际长度
} SqList;//顺序表的类型名
五、注意问题
1.插入、删除时元素的移动原因、方向及先后顺序。
4.三元组表是线性表的一种应用,通过它可以更好地理解线性表的存储结构。同时矩阵又是图的重要的存储方式,所以这个实验对更好地掌握线性表对将来对图的理解都有极大的帮助。
六、实验报告
根据实验情况和结果撰写并递交实验报告。
实验六 树和二叉树
一、预备知识
1.二叉树的二叉链表存储结构
数据结构课程设计
“数据结构”课程设计报告二叉排序树的查找与性能分析学生姓名:段晓宣,张静指导教师:陈少军所在系:电子信息系所学专业:计算机科学与技术年级: 2010级计算机(1)班目录第一章需求分析1.1选题要求 (3)1.2选题的背景与意义 (3)1.3本组课程设计的目标 (3)1.4人员组成和分工 (3)第2章概要分析 (4)2.1系统数据流图 (4)2.2原始数据 (4)2.3输出数据 (4)2.4对数据的处理 (5)2.5数据结构 (5)2.6模块划分 (5)第3章详细设计 (6)3.1二叉排序树的创建 (6)3.2二叉排序树的插入 (7)3.3二叉排序树的查找 (7)3.4计算多数据的平均查找长度 (9)3.5主函数 (9)第4章用户手册 (10)4.1 用户须知 (10)第5章系统测试 (11)项目总结 (12)参考文献 (13)二叉树排序树的查找与性能分析摘要:21世纪是信息化的时代,计算机深入到生活的各个领域。
随着计算机的发展,许多高科技产品如雨后春笋应运而生。
但究其本质而言,无非是以前的理论加以包装。
对于数据控制、管理及处理等方面也可见一斑。
在如今应用的计算机的数据存储方式仍然主要以线性,树型,图型等为主要的及结构。
因此了解并掌握数据结构的知识是很有必要的。
在此次实训期间,本组人员通过运用所学数据结构的知识,进行以二叉排序树的查找与性能分析为题的课程设计,在同组人员的共同努力下,基本实现了:1.创建二叉排序树2.利用文件存储二叉排序树3.二叉排序树的插入4.二叉排序树的查找5.二叉排序树平均查找长度的算法第1章需求分析1.1选题要求(1)根据输入的先序及递归建立二叉排序树;(2)通过文件,向二叉排序树插入结点,并生成二叉树;(3)设置报名号为关键字,可以根据关键字进行查找;(5)查找的同时可以判断比较的次数;(6)根据查找的算法计算出10000个数据平均查找长度;1.2选题的背景与意义(1)树型存储结构数据存储结构中重要的组成部分,二叉树由是树的重点。
数据结构-二叉排序树
二叉排序树操作一、设计步骤1)分析课程设计题目的要求2)写出详细设计说明3)编写程序代码,调试程序使其能正确运行4)设计完成的软件要便于操作和使用5)设计完成后提交课程设计报告(一)程序功能:1)创建二叉排序树2)输出二叉排序树3)在二叉排序树中插入新结点4)在二叉排序树中删除给定的值5)在二叉排序树中查找所给定的值(二)函数功能:1) struct BiTnode 定义二叉链表结点类型包含结点的信息2) class BT 二叉排序树类,以实现二叉排序树的相关操作3) InitBitree() 构造函数,使根节点指向空4) ~BT () 析构函数,释放结点空间5) void InsertBST(&t,key) 实现二叉排序树的插入功能6) int SearchBST(t,key) 实现二叉排序树的查找功能7) int DelBST(&t,key) 实现二叉排序树的删除功能8) void InorderBiTree (t) 实现二叉排序树的排序(输出功能)9) int main() 主函数,用来完成对二叉排序树类中各个函数的测试二、设计理论分析方法(一)二叉排序树定义首先,我们应该明确所谓二叉排序树是指满足下列条件的二叉树:(1)左子树上的所有结点值均小于根结点值;(2)右子数上的所有结点值均不小于根结点值;(3)左、右子数也满足上述两个条件。
根据对上述的理解和分析,我们就可以先创建出一个二叉链表结点的结构体类型(struct BiTNode)和一个二叉排序树类(class BT),以及类中的构造函数、析构函数和其他实现相关功能的函数。
(二)插入函数(void InsertBST(&t,key))首先定义一个与BiTNode<k> *BT同一类型的结点p,并为其申请空间,使p->data=key,p->lchild和p->rchild=NULL。
数据结构二叉排序树
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
数据结构:第9章 查找2-二叉树和平衡二叉树
return(NULL); else
{if(t->data==x) return(t);
if(x<(t->data) return(search(t->lchild,x));
else return(search(t->lchild,x)); } }
——这种既查找又插入的过程称为动态查找。 二叉排序树既有类似于折半查找的特性,又采用了链表存储, 它是动态查找表的一种适宜表示。
注:若数据元素的输入顺序不同,则得到的二叉排序树形态 也不同!
讨论1:二叉排序树的插入和查找操作 例:输入待查找的关键字序列=(45,24,53,45,12,24,90)
二叉排序树的建立 对于已给定一待排序的数据序列,通常采用逐步插入结点的方 法来构造二叉排序树,即只要反复调用二叉排序树的插入算法 即可,算法描述为: BiTree *Creat (int n) //建立含有n个结点的二叉排序树 { BiTree *BST= NULL;
for ( int i=1; i<=n; i++) { scanf(“%d”,&x); //输入关键字序列
– 法2:令*s代替*p
将S的左子树成为S的双亲Q的右子树,用S取代p 。 若C无右子树,用C取代p。
例:请从下面的二叉排序树中删除结点P。
F P
法1:
F
P
C
PR
C
PR
CL Q
CL QL
Q SL
S PR
QL S
SL
法2:
F
PS
C
PR
CL Q
QL SL S SL
数据结构 -第12周查找第3讲-二叉排序树.pdf
以二叉树或树作为表的组织形式,称为树表,它是一类动态查找表,不仅适合于数据查找,也适合于表插入和删除操作。
常见的树表:二叉排序树平衡二叉树B-树B+树9.3.1 二叉排序树二叉排序树(简称BST)又称二叉查找(搜索)树,其定义为:二叉排序树或者是空树,或者是满足如下性质(BST性质)的二叉树:❶若它的左子树非空,则左子树上所有节点值(指关键字值)均小于根节点值;❷若它的右子树非空,则右子树上所有节点值均大于根节点值;❸左、右子树本身又各是一棵二叉排序树。
注意:二叉排序树中没有相同关键字的节点。
二叉树结构满足BST性质:节点值约束二叉排序树503080209010854035252388例如:是二叉排序树。
66不试一试二叉排序树的中序遍历序列有什么特点?二叉排序树的节点类型如下:typedef struct node{KeyType key;//关键字项InfoType data;//其他数据域struct node*lchild,*rchild;//左右孩子指针}BSTNode;二叉排序树可看做是一个有序表,所以在二叉排序树上进行查找,和二分查找类似,也是一个逐步缩小查找范围的过程。
1、二叉排序树上的查找Nk< bt->keybtk> bt->key 每一层只和一个节点进行关键字比较!∧∧p查找到p所指节点若k<p->data,并且p->lchild=NULL,查找失败。
若k>p->data,并且p->rchild=NULL,查找失败。
查找失败的情况加上外部节点一个外部节点对应某内部节点的一个NULL指针递归查找算法SearchBST()如下(在二叉排序树bt上查找关键字为k的记录,成功时返回该节点指针,否则返回NULL):BSTNode*SearchBST(BSTNode*bt,KeyType k){if(bt==NULL||bt->key==k)//递归出口return bt;if(k<bt->key)return SearchBST(bt->lchild,k);//在左子树中递归查找elsereturn SearchBST(bt->rchild,k);//在右子树中递归查找}在二叉排序树中插入一个关键字为k的新节点,要保证插入后仍满足BST性质。
数据结构实验三——二叉树基本操作及运算实验报告
《数据结构与数据库》实验报告实验题目二叉树的基本操作及运算一、需要分析问题描述:实现二叉树(包括二叉排序树)的建立,并实现先序、中序、后序和按层次遍历,计算叶子结点数、树的深度、树的宽度,求树的非空子孙结点个数、度为2的结点数目、度为2的结点数目,以及二叉树常用运算。
问题分析:二叉树树型结构是一类重要的非线性数据结构,对它的熟练掌握是学习数据结构的基本要求。
由于二叉树的定义本身就是一种递归定义,所以二叉树的一些基本操作也可采用递归调用的方法。
处理本问题,我觉得应该:1、建立二叉树;2、通过递归方法来遍历(先序、中序和后序)二叉树;3、通过队列应用来实现对二叉树的层次遍历;4、借用递归方法对二叉树进行一些基本操作,如:求叶子数、树的深度宽度等;5、运用广义表对二叉树进行广义表形式的打印。
算法规定:输入形式:为了方便操作,规定二叉树的元素类型都为字符型,允许各种字符类型的输入,没有元素的结点以空格输入表示,并且本实验是以先序顺序输入的。
输出形式:通过先序、中序和后序遍历的方法对树的各字符型元素进行遍历打印,再以广义表形式进行打印。
对二叉树的一些运算结果以整型输出。
程序功能:实现对二叉树的先序、中序和后序遍历,层次遍历。
计算叶子结点数、树的深度、树的宽度,求树的非空子孙结点个数、度为2的结点数目、度为2的结点数目。
对二叉树的某个元素进行查找,对二叉树的某个结点进行删除。
测试数据:输入一:ABC□□DE□G□□F□□□(以□表示空格),查找5,删除E预测结果:先序遍历ABCDEGF中序遍历CBEGDFA后序遍历CGEFDBA层次遍历ABCDEFG广义表打印A(B(C,D(E(,G),F)))叶子数3 深度5 宽度2 非空子孙数6 度为2的数目2 度为1的数目2查找5,成功,查找的元素为E删除E后,以广义表形式打印A(B(C,D(,F)))输入二:ABD□□EH□□□CF□G□□□(以□表示空格),查找10,删除B预测结果:先序遍历ABDEHCFG中序遍历DBHEAGFC后序遍历DHEBGFCA层次遍历ABCDEFHG广义表打印A(B(D,E(H)),C(F(,G)))叶子数3 深度4 宽度3 非空子孙数7 度为2的数目2 度为1的数目3查找10,失败。
数据结构与算法实验测试题
1 2 3 4 51 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20分别随机建立一个含N个整数的链接线性表和顺序线性表(输出),再按奇偶数分存于两个分别用顺序结构和链接结构建立栈和队,再随机产生N个整数入队,并利用栈分别将它们依利用计算机存储特点,建立一个能够存储任意矩阵的类,并用它的两个实例来存储随机矩阵A MN及其转置矩阵(均输出)。
随机产生N个整数,建立二叉排序树,中序遍历,并计算其叶子数和树高,随机建立一个N个顶点M条边的无向图,用邻接矩阵存储,输出全部的边,并求编号最小和编(以上5题为必做题,每个文件,类,函数及特别变量都必须有注释)(以下为选作题,当然有加分的)随机建立一个含N个整数的顺序表,输出,就地逆置后再输出。
随机建立一个含N个整数的链接,输出,就地逆置后再输出。
建立一个三元组矩阵存储类,并随机初始化一个三元组实例(表示某稀疏矩阵),将其按普随机初始化一稀疏矩阵,将其转存储到一个三元组矩阵中,并输出该三元组矩阵及原稀疏矩随机产生N个整数,建立二叉排序树,按先序,中序,后序,层序进行遍历。
随机产生N个整数,建立二叉排序树,并进行能进行对指定结点的删除操作。
随机产生N个整数(输出),利用改进冒泡排序方法进行排序后再输出。
随机产生N个整数(输出),利用简单选择排序方法进行排序后再输出。
随机产生N个整数(输出),利用直接插入泡排序方法进行排序后再输出。
随机产生N个整数(输出),利用归并排序方法进行排序后再输出。
随机产生N个整数(输出),利用堆排序方法进行排序后再输出。
随机初始化N个元素的整数数组,利用顺序查找定位指定的元素。
随机初始化N个元素的有序整数数组,利用二分迭代方法,定位指定元素位置。
随机初始化N个元素的有序整数数组,利用二分递归算法,定位指定元素位置。
随机产生N个整数(输出),就地将其进行奇偶分区后再输出。
随机产生N个整数(输出),找出其最大和次大的偶数。
数据结构试题(含答案)
数据结构试题(含答案)一.是非题(勾选“√“用于更正和勾选”√1.数据结构可用三元公式(D,s,P)表示,其中:D为数据对象,s为D上的关系,p是对d的基本操作集。
×2.线性表的链式存储结构具有直接访问表中任何元素的优点。
×3. 字符串是特定于数据对象的线性表。
4.二叉树是一棵结点的度最大为二的树。
×5.邻接多表可用于表示无向图或有向图。
×6. 所有顶点的拓扑序都可以从任何有向图中得到。
× 7. 无向连通图的生成树是其最大连通子图。
× 8. 二叉排序树的搜索长度最多为log2n。
×9.对于一棵m阶的b-树.树中每个结点至多有m个关键字。
除根之外的所有非终端结点至几乎没有┌ M/2┌ 关键词。
×10.对于目前所知的排序方法,快速排序具有最好的平均性能。
11.顺序存储模式具有存储密度高、插入和删除操作效率高的优点。
× 12. 二维数组是一个线性表,其数据元素是线性表。
13.连通图g的生成树是一个包含g的所有n个顶点和n-1条边的子图。
×14.折半查找不适用于有序链表的查找。
15.完全二叉树必定是平衡二叉树。
16.中间顺序线索二叉树的优点是,在中间顺序下很容易找到直接前导节点和直接后继节点。
17.队列是一种完全不同于线性表的数据结构。
× 18. 平均搜索长度与记录的搜索概率有关。
19.二叉树中每个结点有两个子结点,而对一般的树,则无此限制,所以,二叉树是树的特殊情形。
×20.算法的时间复杂度越高,可读性越差;相反,算法的可读性越好,时间复杂度越差。
×二.选择题1.如果编号为1、2和3的列车车厢依次通过开关堆调度,则无法获得(E)的顺序。
a:1,2,3b:1,3,2c:2,1,3d:2,3,1e:3,1,2f:3,2,12.递归程序可借助于(b)转化为非递归程序。
a:线性表B:堆栈C:队列D:数组3.在下列数据结构中(c)具有先进先出(fifo)特性,(b)它具有先进先出的特点。
二叉排序树(二叉链表结构存储)数据结构课程设计报告
二叉排序树(二叉链表结构存储)数据结构课程设计报告目录1需求分析 (1)1.1课程设计题目、任务及要求 (1)1.2课程设计思想 (1)2概要设计 (2)2.1 二叉排序树的定义 (2)2.2二叉链表的存储结构 (2)2.3建立二叉排序树 (2)2.4二叉排序树的生成过程 (3)2.5中序遍历二叉树 (3)2.6二叉排序树的查找 (3)2.7二叉排序树的插入 (4)2.8平均查找长度 (4)3详细设计和实现 (4)3.1主要功能模块设计 (4)3.2主程序设计 (5)4调试与操作说明 (12)4.1程序调试 (12)4.2程序操作说明 (13)总结 (16)致谢 (17)参考文献 (19)1需求分析1.1课程设计题目、任务及要求二叉排序树。
用二叉链表作存储结构(1)以(0)为输入结束标志,输入数列L,生成一棵二叉排序树T;(2)对二叉排序树T作中序遍历,输出结果;(3)计算二叉排序树T查找成功的平均查找长度,输出结果;(4)输入元素x,查找二叉排序树T:若存在含x的结点,则删除该结点,并作中序遍历(执行操作2);否则输出信息“无x”;1.2课程设计思想建立二叉排序树采用边查找边插入的方式。
查找函数采用递归的方式进行查找。
如果查找成功则不应再插入原树,否则返回当前结点的上一个结点。
然后利用插入函数将该元素插入原树。
对二叉排序树进行中序遍历采用递归函数的方式。
在根结点不为空的情况下,先访问左子树,再访问根结点,最后访问右子树。
由于二叉排序树自身的性质,左子树小于根结点,而根结点小于右子树,所以中序遍历的结果是递增的。
计算二插排序树的平均查找长度时,仍采用类似中序遍历的递归方式,用s记录总查找长度,j记录每个结点的查找长度,s置初值为0,采用累加的方式最终得到总查找长度s。
平均查找长度就等于s/i(i为树中结点的总个数)。
删除结点函数,采用边查找边删除的方式。
如果没有查找到,则不对树做任何的修改;如果查找到结点,则分四种情况分别进行讨论:1、该结点左右子树均为空;2、该结点仅左子树为空;3、该结点仅右子树为空;4、该结点左右子树均不为空。
数据结构与算法(3):二叉树
1.3.3 性质三
包含n个结点的二二叉树的高高度至至少为log2(n + 1);
证明:根据"性质2"可知,高高度为h的二二叉树最多有2{h}–1个结点。反之,对于包含n个节点的二二
叉树的高高度至至少为log2(n + 1)。
1.3.4 性质四
对任何一一颗二二叉树T,如果其终端结点数为n0 ,度为2的结点数为n2 ,则n0 = n2 + 1 证明:因为二二叉树中所有结点的度数均不不大大于2,所以结点总数(记为n)="0度结点数(n0)" + "1度 结点数(n1)" + "2度结点数(n2)"。由此,得到等式一一。(等式一一) n = n0 + n1 + n2
}
还有一一种方方式就是利利用用栈模拟递归过程实现循环先序遍历二二叉树。这种方方式具备扩展性,它模拟 了了递归的过程,将左子子树不不断的压入入栈,直到null,然后处理理栈顶节点的右子子树。
java
public void preOrder(Node root){ if(root==null)return;
2. 叶子子数为2h 3. 第k层的结点数是:2k−1; 4. 总结点数是2k − 1,且总节点数一一定是奇数。
1.4.2 完全二二叉树
定义:一一颗二二叉树中,只有最小小面面两层结点的度可以小小于2,并且最下一一层的叶结点集中在靠左 的若干干位置上。这样现在最下层和次下层,且最小小层的叶子子结点集中在树的左部。显然,一一颗 满二二叉树必定是一一颗完全二二叉树,而而完全二二叉树未必是满二二叉树。
} root = s.pop(); root = root.right;//如果是null,出栈并处理理右子子树 } }
数据结构_第9章_查找2-二叉树和平衡二叉树
F
PS
C
PR
CL Q
QL SL S SL
10
3
18
2
6 12
6 删除10
3
18
2
4 12
4
15
15
三、二叉排序树的查找分析
1) 二叉排序树上查找某关键字等于给定值的结点过程,其实 就是走了一条从根到该结点的路径。 比较的关键字次数=此结点的层次数; 最多的比较次数=树的深度(或高度),即 log2 n+1
-0 1 24
0 37
0 37
-0 1
需要RL平衡旋转 (绕C先顺后逆)
24
0
-012
13
3573
0
01
37
90
0 53 0 53
0 90
作业
已知如下所示长度为12的表:
(Jan, Feb, Mar, Apr, May, June, July, Aug, Sep, Oct, Nov, Dec)
(1) 试按表中元素的顺序依次插入一棵初始为空的二叉 排序树,画出插入完成之后的二叉排序树,并求其在 等概率的情况下查找成功的平均查找长度。
2) 一棵二叉排序树的平均查找长度为:
n i1
ASL 1
ni Ci
m
其中:
ni 是每层结点个数; Ci 是结点所在层次数; m 为树深。
最坏情况:即插入的n个元素从一开始就有序, ——变成单支树的形态!
此时树的深度为n ; ASL= (n+1)/2 此时查找效率与顺序查找情况相同。
最好情况:即:与折半查找中的判ห้องสมุดไป่ตู้树相同(形态比较均衡) 树的深度为:log 2n +1 ; ASL=log 2(n+1) –1 ;与折半查找相同。
二叉排序树与平衡二叉排序树基本操作的实现 文本文档
10 设计说明书(论文)质量 30 综述简练完整,有见解;立论正确,论述充分,结论严谨合理;实验正确,分析处理科学。
11 创新 10 对前人工作有改进或突破,或有独特见解。
成绩
指导教师评语
指导教师签名: 年 月 日
摘要及关键字
本程序中的数据采用“树形结构”作为其数据结构。具体采用的是“二叉排序树”。
1.2.5 平衡二叉树( AVL树 )
①平衡二叉树(Balanced Binary Tree)是指树中任一结点的左右子树的高度大致相同。 ②任一结点的左右子树的高度均相同(如满二叉树),则二叉树是完全平衡的。通常,只要二叉树的高度为O(1gn),就可看作是平衡的。 ③平衡的二叉排序树指满足BST性质的平衡二叉树。 ④AVL树中任一结点的左、右子树的高度之差的绝对值不超过1。在最坏情况下,n个结点的AVL树的高度约为1.44lgn。而完全平衡的二叉树高度约为lgn,AVL树是最接近最优的。
1.2.4平均查找长度…………………………………………………………… 6
1.2.5平均二叉树(AVL树)…………………………………………………… 6
1.2.6平衡因子………………………………………………………………… 7
1.2.7平衡二叉树的调整方法…………………………………………………… 7
攀枝花学院本科学生课程设计任务书
题 目 二叉排序树与平衡二叉树的实现
1、课程设计的目的
使学生进一步理解和掌握课堂上所学各种基本抽象数据类型的逻辑结构、存储结构和操作实现算法,以及它们在程序中的使用方法。
使学生掌握软件设计的基本内容和设计方法,并培养学生进行规范化软件设计的能力。
3) 使学生掌握使用各种计算机资料和有关参考资料,提高学生进行程序设计的基本能力。
数据结构与算法复习题
数据结构与算法复习题一、写出以下各词语对应的中文(英)sequential storgestructure 顺序存储结构AbstractDataType (ADT) 抽象数据类型二叉排序树Binary sort treequeue 队列storgestructure存储结构time complexity 时间复杂度线性表LinearList二叉树BinaryTreeDepth_First Search深度优先搜索singly linked lists单链表二、单项选择题1、数据结构是一门研究非数值计算的程序设计问题中数据元素的、数据信息在计算机中的存储结构以及一组相关的运算等的课程。
A: 操作对象B: 计算方法C:逻辑结构D: 数据映象2、某线性表最常用的运算是插入和删除,插入运算是指在表尾插入一个新元素,删除运算是指删除表头第一个元素,那么采用存储方式最节省运算时间.。
A: 仅有头指针的单向循环链表B: 仅有尾指针的单向循环链表ﻩC: 单向链表D:双向链表3、一个栈的入栈序列是a,b,c,d,e,则栈的不可能的输出序列是____。
A: abcde B:decbaC: edcbaD: dceab4、将一个递归算法改为对应的非递归算法时,通常需要使用_____。
A: 栈B:队列ﻩ C:循环队列D:优先队列5、关于空串,下列说法中正确的有____。
A:空串就是空格串B: 空串的长度可能不为零C: 空串是零个字符的串D: 空串的长度就是其包含的空格个数6、二维数组A中,每个元素的长度为3个字节,行下标i从0到7,列下标j从0到9,从首地址SA开始连续存放在存储器内,该数组按行存放时,数组元素A[7][4]的起始地址为。
A:SA+141B:SA+144C:SA+222 D: SA+2257、某二叉树的前序和后序序列正好相反,则该二叉树一定是 的二叉树。
A : 空或只有一个结点B : 高度等于其结点数ﻩC : 任一结点无左孩子 ﻩD : 任一结点无右孩子8、下述4棵二叉树中,是完全二叉树的是: 。
数据结构专题实验
上机实验要求及规范《数据结构》课程具有比较强的理论性,同时也具有较强的可应用性和实践性,因此上机实验是一个重要的教学环节。
一般情况下学生能够重视实验环节,对于编写程序上机练习具有一定的积极性,但是容易忽略实验的总结,忽略实验报告的撰写。
对于一名大学生必须严格训练分析总结能力、书面表达能力。
需要逐步培养书写科学实验报告以及科技论文的能力。
拿到一个题目,一般不要急于编程,而是应该按照面向过程的程序设计思路(关于面向对象的训练将在其它后继课程中进行),首先理解问题,明确给定的条件和要求解决的问题,然后按照自顶向下,逐步求精,分而治之的策略,逐一地解决子问题。
具体步骤如下:1.问题分析与系统结构设计充分地分析和理解问题本身,弄清要求做什么(而不是怎么做),限制条件是什么。
按照以数据结构为中心的原则划分模块,搞清数据的逻辑结构(是线性表还是树、图?),确定数据的存储结构(是顺序结构还是链表结构?),然后设计有关操作的函数。
在每个函数模块中,要综合考虑系统功能,使系统结构清晰、合理、简单和易于调试。
最后写出每个模块的算法头和规格说明,列出模块之间的调用关系(可以用图表示),便完成了系统结构设计。
2.详细设计和编码详细设计是对函数(模块)的进一步求精,用伪高级语言(如类C语言)或自然语言写出算法框架,这时不必确定很多结构和变量。
编码,即程序设计,是对详细设计结果的进一步求精,即用某种高级语言(如C/C++语言)表达出来。
尽量多设一些注释语句,清晰易懂。
尽量临时增加一些输出语句,便于差错矫正,在程序成功后再删去它们。
3.上机准备熟悉高级语言用法,如C语言。
熟悉机器(即操作系统),基本的常用命令。
静态检查主要有两条路径,一是用一组测试数据手工执行程序(或分模块进行);二是通过阅读或给别人讲解自己的程序而深入全面地理解程序逻辑,在这个过程中再加入一些注释和断言。
如果程序中逻辑概念清楚,后者将比前者有效。
4.上机调试程序调试最好分块进行,自底向上,即先调试底层函数,必要时可以另写一个调用驱动程序,表面上的麻烦工作可以大大降低调试时所面临的复杂性,提高工作效率。
数据结构第20讲--二叉排序树--2018
二叉排序树
• 任一结点 > 其左子树的所有结点,并且
< 其右子树的所有结点;
结点的左、右子树,也是二叉排序树;
≠
5
5
左孩子 < 父亲 <右孩子 另外,与堆进行区分!
4 9 49
3 12 7 12
×√
二叉排序树
• 任一结点 > 其左子树,并且
parentp->llink = Null;
else
//若*p是父亲的右孩子
parentp->rlink = Null;
free(p); return 1; //释放空间,返回 }
//2.1 若*p只有右孩子,则让右孩子取代*p
if(p->llink==Null && p->rlink!=Null)
18
< 其右子树; • 重要性质:
中序遍历二叉排序树
10 5
73 68 99
递增序列
4 9 27
• 如何判断1棵二叉树
是否是二叉排序树?
8 25 41
-- 中序遍历,得到递增序列才是。 32 51
二叉排序树--存储结构
struct BinSearchNode; //结点类型声明 typedef struct BinSearchNode * PBinSearchNode; struct BinSearchNode //结点类型
q
p = *ptree; //p指向树根
p
q = p; //后续:q用于记录p的父亲
5
49
7 12
while( p != Null) //p指向当前(子)树的根
广工数据结构实验报告平衡二叉树
数据结构实验报告题目:平衡二叉树学院专业年级班别学号学生姓名指导教师2015年7月1日1.题目:采用字符类型为整型类型和链式存储结构,实现抽象数据类型BTree。
ADT BTree{数据对象:D={a i | a i∈ElemSet,i=1,2,。
.。
,n,n≥0 }数据关系:R1={<a i—1,a i>|a i—1, a i∈D, i=2,。
.,n }基本操作:Adj_balance(T)操作结果:创建平衡二叉树。
InsertA VL(T,search,taller)初始条件:二叉树T已存在。
操作结果:增加新结点。
SetA VL(T,search,taller)初始条件:二叉树T已存在。
操作结果:在平衡二叉树上增加新结点并调平衡.DeleteA VL(T,search,shorter)初始条件:二叉树T已存在.操作结果:删除结点。
}ADT BTree2.存储结构定义公用头文件DS0。
h:#include〈stdio。
h〉#include 〈malloc.h>树的内部变量typedef struct BTNode{int data;int bf; //平衡因子struct BTNode *lchild,*rchild;//左、右孩子}BTNode,*BTree;/*需要的函数声明*/void Right_Balance(BTree &p);void Left_Balance(BTree &p);void Left_Root_Balance(BTree &T);void Right_Root_Balance(BTree &T);bool InsertA VL(BTree &T,int i,bool &taller);void PrintBT(BTree T);void Left_Root_Balance_det(BTree &p,int &shorter);void Right_Root_Balance_det(BTree &p,int &shorter);void Delete(BTree q,BTree &r,int &shorter);int DeleteA VL(BTree &p,int x,int &shorter);void Adj_balance(BTree &T);bool SetA VL(BTree &T,int i,bool &taller);bool Insert_Balance_A VL(BTree &T,int i,bool &taller);int menu();3.算法设计/*对以*p为根的二叉排序树作右旋处理*/void Right_Balance(BTree &p){BTree lc;lc =p-〉lchild;//lc指向的*p左子树根结点p->lchild = lc-〉rchild;//rc的右子树挂接为*p的左子树lc—〉rchild = p;p = lc; //p指向新的结点}/*对以*p为根的二叉排序树作左旋处理*/void Left_Balance(BTree &p){BTree rc;rc = p-〉rchild;//指向的*p右子树根结点p—〉rchild = rc—〉lchild;//rc左子树挂接到*p的右子树rc->lchild = p;p = rc; //p指向新的结点}/*对以指针T所指结点为根的二叉树作左平衡旋转处理*/void Left_Root_Balance(BTree &T){BTree lc,rd;lc = T-〉lchild;//指向*T的左子树根结点switch(lc->bf)//检查*T的左子树的平衡度,并作相应平衡处理{case 1://新结点插入在*T的左孩子的左子树上,要作单右旋处理T—〉bf = lc—>bf = 0;Right_Balance(T);break;case -1://新结点插入在*T的左孩子的右子树上,要作双旋处理rd = lc—〉rchild; //rd指向*T的左孩子的右子树根switch(rd-〉bf)//修改*T及其左孩子的平衡因子{case 1:T-〉bf = -1;lc—>bf = 0;break;case 0:T->bf = lc—>bf = 0;break;case —1:T-〉bf = 0;lc—〉bf = 1;break;}rd—〉bf = 0;Left_Balance(T->lchild); //对*T的左子树作左旋平衡处理Right_Balance(T);//对*T作右旋平衡处理}}/*对以指针T所指结点为根的二叉树作右平衡旋转处理*/void Right_Root_Balance(BTree &T){BTree rc,ld;rc = T—>rchild;//指向*T的左子树根结点switch(rc—〉bf)//检查*T的右子树的平衡度,并作相应平衡处理{case -1://新结点插入在*T的右孩子的右子树上,要作单左旋处理T-〉bf = rc-〉bf =0;Left_Balance(T);break;case 1://新结点插入在*T的右孩子的左子树上,要作双旋处理ld = rc—〉lchild; //ld指向*T的右孩子的左子树根switch(ld—>bf)//修改*T及其右孩子的平衡因子{case 1:T->bf = 0;rc—>bf = -1;break;case 0:T—>bf = rc->bf =0;break;case -1:T—>bf = 1;rc—>bf = 0;break;}ld—〉bf = 0;Right_Balance(T-〉rchild);//对*T的右子树作左旋平衡处理Left_Balance(T); //对*T作左旋平衡处理}}/*插入结点i,若T中存在和i相同关键字的结点,则插入一个数据元素为i的新结点,并返回1,否则返回0*/bool InsertA VL(BTree &T,int i,bool &taller){if(!T)//插入新结点,树“长高”,置taller为true{T = (BTree)malloc(sizeof(BTNode));T-〉data = i;T—>lchild = T—>rchild =NULL;T-〉bf = 0;taller = true;}else{if(i==T—〉data) //树中已存在和有相同关键字的结点{taller = 0;printf("已存在相同关键字的结点\n”);return 0;}if(i〈T—〉data) //应继续在*T的左子树中进行搜索{if(!InsertA VL(T->lchild,i,taller))return 0;}else //应继续在*T的右子树中进行搜索{if(!InsertA VL(T—〉rchild,i,taller))return 0;}}return 1;}/*输出二叉树*/void PrintBT(BTree T){if(T){printf(”%d",T->data);if(T-〉lchild||T-〉rchild){printf("(");PrintBT(T—〉lchild);printf(",”);PrintBT(T->rchild);printf(”)”);}}}/*删除结点时左平衡旋转处理*/void Left_Root_Balance_det(BTree &p,int &shorter){BTree p1,p2;if(p->bf==1)//p结点的左子树高,删除结点后p的bf减,树变矮{p—>bf=0;shorter=1;}else if(p->bf==0)//p结点左、右子树等高,删除结点后p的bf减,树高不变{p-〉bf=—1;shorter=0;}else //p结点的右子树高{p1=p—>rchild;//p1指向p的右子树if(p1—〉bf==0)//p1结点左、右子树等高,删除结点后p的bf为—2,进行左旋处理,树高不变{Left_Balance(p);p1—>bf=1;p-〉bf=-1;shorter=0;}else if(p1-〉bf==-1)//p1的右子树高,左旋处理后,树变矮{Left_Balance(p);p1—〉bf=p—>bf=0;shorter=1;}else //p1的左子树高,进行双旋处理(先右旋后左旋),树变矮{p2=p1—〉lchild;p1—〉lchild=p2—>rchild;p2—〉rchild=p1;p—>rchild=p2-〉lchild;p2—>lchild=p;if(p2—〉bf==0){p->bf=0;p1—>bf=0;}else if(p2-〉bf==—1){p-〉bf=1;p1—>bf=0;}else{p-〉bf=0;p1—>bf=—1;}p2-〉bf=0;p=p2;shorter=1;}}}/*删除结点时右平衡旋转处理*/void Right_Root_Balance_det(BTree &p,int &shorter){BTree p1,p2;if(p-〉bf==-1){p->bf=0;shorter=1;}else if(p-〉bf==0){p—>bf=1;shorter=0;}else{p1=p->lchild;if(p1—〉bf==0){Right_Balance(p);p1—>bf=—1;p—>bf=1;shorter=0;}else if(p1->bf==1){Right_Balance(p);p1->bf=p—>bf=0;shorter=1;}else{p2=p1—>rchild;p1—〉rchild=p2—〉lchild;p2-〉lchild=p1;p->lchild=p2—>rchild;p2->rchild=p;if(p2-〉bf==0){p—〉bf=0;p1->bf=0;}else if(p2-〉bf==1){p—〉bf=—1;p1—>bf=0;}else{p-〉bf=0;p1->bf=1;}p2->bf=0;p=p2;shorter=1;}}}/*删除结点*/void Delete(BTree q,BTree &r,int &shorter) {if(r-〉rchild==NULL){q—〉data=r->data;q=r;r=r—>lchild;free(q);shorter=1;}else{Delete(q,r—>rchild,shorter);if(shorter==1)Right_Root_Balance_det(r,shorter);}}/*二叉树的删除操作*/int DeleteA VL(BTree &p,int x,int &shorter){int k;BTree q;if(p==NULL){printf("不存在要删除的关键字!!\n");return 0;}else if(x<p-〉data)//在p的左子树中进行删除{k=DeleteA VL(p-〉lchild,x,shorter);if(shorter==1)Left_Root_Balance_det(p,shorter);return k;}else if(x>p->data)//在p的右子树中进行删除{k=DeleteA VL(p—>rchild,x,shorter);if(shorter==1)Right_Root_Balance_det(p,shorter);return k;}else{q=p;if(p->rchild==NULL)//右子树空则只需重接它的左子树{p=p—>lchild;free(q);shorter=1;}else if(p->lchild==NULL)//左子树空则只需重接它的右子树{p=p—>rchild;free(q);shorter=1;}else//左右子树均不空{Delete(q,q->lchild,shorter);if(shorter==1)Left_Root_Balance_det(p,shorter);p=q;}return 1;}}/*调平二叉树具体方法*/bool SetA VL(BTree &T,int i,bool &taller){if(!T)//插入新结点,树“长高”,置taller为true{T = (BTree)malloc(sizeof(BTNode));T-〉data = i;T—〉lchild = T—〉rchild =NULL;T—>bf = 0;taller = true;}else{if(i==T-〉data) //树中已存在和有相同关键字的结点{taller = false;printf("已存在相同关键字的结点\n”);return 0;}if(i〈T—〉data)//应继续在*T的左子树中进行搜索{if(!SetA VL(T->lchild,i,taller))return 0;if(taller) //已插入到*T的左子树中且左子树“长高”switch(T—>bf)//检查*T的平衡度{case 1://原本左子树比右子树高,需要作左平衡处理Left_Root_Balance(T);taller = false;break;case 0: //原本左子树、右子等高,现因左子树增高而使树增高T->bf = 1;taller = true;break;case -1: //原本右子树比左子树高,现左、右子树等高T—〉bf = 0;taller = false;break;}}else //应继续在*T的右子树中进行搜索{if(!SetA VL(T—〉rchild,i,taller))return 0;if(taller) //已插入到*T的右子树中且右子树“长高”switch(T-〉bf)//检查*T的平衡度{case 1://原本左子树比右子树高,现左、右子树等高T-〉bf = 0;taller = false;break;case 0: //原本左子树、右子等高,现因右子树增高而使树增高T-〉bf = -1;taller = true;break;case —1://原本右子树比左子树高,需要作右平衡处理Right_Root_Balance(T);taller = false;break;}}return 1;}}/*二叉树调平操作*/void Adj_balance(BTree &T){int i;bool taller=false;T = NULL;printf(”\n请输入关键字(以—1结束建立平衡二叉树):");scanf("%d",&i);getchar();while(i != -1){SetA VL(T,i,taller);printf("\n请输入关键字(以-1结束建立平衡二叉树):”);scanf(”%d",&i);getchar();taller=false;}printf("平衡二叉树创建结束。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
建立二叉排序树
1 需求分析
1. 本实验要求根据输入一组数据创建排序二叉树,并求该树的深度。
2. 输入形式:键盘输入;
输入范围:一组数字,顺序任意,以-1为结束标志。
3. 实现功能:对输入的一组数字利用二叉树结构进行存储(称为排序二叉树),并求该树深度。
4. 测试数据
2 概要设计
2.1 问题分析
对于大量数据,如果直接逐一存储数据,那么在进行查找时只能运用查找顺序表的方法。
即使运用相关的算法,时间复杂度也相当大。
鉴于这样的缺陷,我们需要在存储数据数据时就选择有利于未来查找的存储结构,查找二叉树就是这样的一种结构。
对于查找二叉树中的任一元素,如果有左子,其左子树各结点的数据必须小于该元素;如果有右子,其右子树各结点的数据必须大于或等于该元素。
对于求一棵树的深度,首先自然想到树的遍历。
因为对树进行中序、后序遍历时,首先输出的元素位于树深度最大处。
在寻找中序、后序遍历首元素的同时,记录查找的层数,即可得到该树的深度。
2.2 算法分析
1)创建排序二叉树
设已知一组待排序的数据,若要构造出对应的一个查找二叉树,一般是采取从空数开始,陆续插入一系列结点,逐步生成二叉树。
在插入过程中,原有的结点位置均不在变动,只是将新的数据结点插入到合适的位置,
使得树中任何结点的数
据与其左、右子树结点数据之间的关系都符合对查找二叉树的要求。
2)求数深度
程序运用非递归算法求树的深度。
在求深度函数中,需要调用判断当前结点孩子情况的函数:
定义为int childrenstate(BiTree cPtr)
另外,我们调用深度记录函数,定义两个全局变量:层数level 深度depth。
当调用深度记录函数时,level自加1;当level值大于depth时,用level刷新depth。
同时,也需编写入栈、出栈函数。
通过以上准备后,我们设计出求树深度的具体算法:
当函数childrenstate 返回值为0时,指针移向出栈元素,然后指向该元素右指针;其返回值不为0时,执行以下操作:
返回值为1——当前元素及指针入栈,指针指向其左指针;
2——指针指向当前元素左指针;
3——指针指向当前元素右指针。
算法流程如图:
2.3 程序模块
程度包括三个主要模块:主函数、创建排序二叉树函数和求深度函数。
函数间的调用关系如下图:
3 详细设计
1. 结点、栈的定义
typedef int ElemType;
typedef struct node{
ElemType data;
struct node *lchild;
struct node *rchild;
}BiTNode,* BiTree;
typedef struct stack{
BiTree pointer;
int order;
}StackNode,* StackList;
typedef struct depthstack{
BiTree pointer;
int dep;
}DepthStackNode,* DepthStackList;
//其中一个元素是结构体指针
2. 主函数
void main()
{
BiTree root=NULL;
printf("Please enter data in each node:\n");
printf("(The number -1 is considered as the end of the data)\n");
root=Create(root);
Depth(root);
printf("The depth of the binary search tree is:\n");
printf("%d\n",depth);
}
3. 创建排序二叉树函数
1)插入元素
BiTree Insert(BiTree rPtr,ElemType element)
{
BiTree cPtr,newPtr;
int i=1;
newPtr=Initiate(newPtr);
newPtr->data=element;
if(rPtr==NULL)
rPtr=newPtr;
else{
cPtr=rPtr;
while(i){
if(cPtr->data>element){
if(cPtr->lchild!=NULL)
cPtr=cPtr->lchild;
else{
cPtr->lchild=newPtr;
i=0;
}
}
else{
if(cPtr->rchild!=NULL)
cPtr=cPtr->rchild;
else{
cPtr->rchild=newPtr;
i=0;
}
}
}
}
return rPtr;
}
2)生成二叉树
BiTree Create(BiTree rPtr)
{
int element;
while(1){
scanf("%d",&element);
if(element==-1)
break;
rPtr=Insert(rPtr,element);
}
return rPtr;
}
4. 求深度函数
void Depth(BiTree rPtr)
{
BiTree cPtr;
cPtr=rPtr;
top=0;
depthsta[top].pointer=rPtr;
depthsta[top].dep=level+1;
do{
while(childrenstate(cPtr)){
depthmark();
if(childrenstate(cPtr)==1){
DepthPush(cPtr);
cPtr=cPtr->lchild;
}
else if(childrenstate(cPtr)==2)
cPtr=cPtr->lchild;
else if(childrenstate(cPtr)==3)
cPtr=cPtr->rchild;
}
depthmark();
cPtr=DepthPop();
cPtr=cPtr->rchild;
}while(top!=-1);
}
4 程序使用说明及测试结果
1. 使用说明
进入程序后,输入一组数字,以空格为间隔,以-1为结束标志。
2. 测试结果
5 实验总结
本实验主要是对前面所学内容的应用。
基于二叉排序树的算法思想,利用树中元素插入的基本操作得以实现。
求树的深度也是基于树的中序遍历思想,加入记录数深度的变量即可实现。
由此,在掌握了树的基本操作后,实现本实验难度不大。
另外,需要注意的是在设计栈时,为防止栈空的情况,可以将根结点两次入栈。
这样可以减少一些判断语句的编写。
教师评语:
实验成绩:
指导教师签名:
批阅日期:。