当用线性表作为表的组织形式时,可以有三种查找法。其中以二分查找效率最高。但由于二分查找要求表中结点按关键字有序,且不能用链表作存储结构,因此,当表的插入或删除操作频繁时,为维护表的有序性,势必要移动表中很多结点。这种由移动结点引起的额外时间开销,就会抵消二分查找的优点。也就是说,二分查找只适用于静态查找表。若要对动态查找表进行高效率的查找,可采用下面介绍的几种特殊的二叉树或树作为表的组织形式。不妨将它们统称为树表。下面将分别讨论在这些树表上进行查找和修改操作的方法。
二叉排序树
1、二叉排序树的定义
二叉排序树(Binary Sort Tree)又称二叉查找(搜索)树(Binary Search Tree)。其定义为:二叉排序树或者是空树,或者是满足如下性质的二叉树:
①若它的左子树非空,则左子树上所有结点的值均小于根结点的值;
②若它的右子树非空,则右子树上所有结点的值均大于根结点的值;
③左、右子树本身又各是一棵二叉排序树。
上述性质简称二叉排序树性质(BST性质),故二叉排序树实际上是满足BST性质的二叉树。
2、二叉排序树的特点
由BST性质可得:
(1)二叉排序树中任一结点x,其左(右)子树中任一结点y(若存在)的关键字必小(大)于x的关键字。
(2)二叉排序树中,各结点关键字是惟一的。
注意:
实际应用中,不能保证被查找的数据集中各元素的关键字互不相同,所以可将二叉排序树定义中BST性质(1)里的"小于"改为"大于等于",或将BST性质(2)里的"大于"改为"小于等于",甚至可同时修改这两个性质。
(3)按中序遍历该树所得到的中序序列是一个递增有序序列。
【例】下图所示的两棵树均是二叉排序树,它们的中序序列均为有序序列:2,3,4,5,7,8。
3、二叉排序树的存储结构
typedef int KeyType; //假定关键字类型为整数
typedef struct node { //结点类型
KeyType key; //关键字项
InfoType otherinfo; //其它数据域,InfoType视应用情况而定,下面不处理它
struct node *lchild,*rchild; //左右孩子指针
} BSTNode;
typedef BSTNode *BSTree; //BSTree是二叉排序树的类型
4、二叉排序树上的运算
(1)二叉排序树的插入和生成
①二叉排序树插入新结点的过程
在二叉排序树中插入新结点,要保证插入后仍满足BST性质。其插入过程是:
(a)若二叉排序树T为空,则为待插入的关键字key申请一个新结点,并令其为根;
(b)若二叉排序树T不为空,则将key和根的关键字比较:
(i)若二者相等,则说明树中已有此关键字key,无须插入。
(ii)若key (iii)若key>T→key,则将它插入根的右子树中。 子树中的插入过程与上述的树中插入过程相同。如此进行下去,直到将key作为一个新的叶结点的关键字插入到二叉排序树中,或者直到发现树中已有此关键字为止。 ②二叉排序树插入新结点的递归算法 【参见参考书目】 ③二叉排序树插入新结点的非递归算法 void InsertBST(BSTree *Tptr,KeyType key) { //若二叉排序树 *Tptr中没有关键字为key,则插入,否则直接返回 BSTNode *f,*p=*TPtr; //p的初值指向根结点 while(p){ //查找插入位置 if(p->key==key) return;//树中已有key,无须插入 f=p; //f保存当前查找的结点 p=(key //若key } //endwhile p=(BSTNode *)malloc(sizeof(BSTNode)); p->key=key; p->lchild=p->rchild=NULL; //生成新结点 if(*TPtr==NULL) //原树为空 *Tptr=p; //新插入的结点为新的根 else //原树非空时将新结点关p作为关f的左孩子或右孩子插入 if(key f->lchild=p; else f->rchild=p; } //InsertBST ④二叉排序树的生成 二叉排序树的生成,是从空的二叉排序树开始,每输入一个结点数据,就调用一次插入算法将它插入到当前已生成的二叉排序树中。生成二叉排序树的算法如下: BSTree CreateBST(void) { //输入一个结点序列,建立一棵二叉排序树,将根结点指针返回 BSTree T=NULL; //初始时T为空树 KeyType key; scanf("%d",&key); //读人一个关键字 while(key){ //假设key=0是输人结束标志 InsertBST(&T,key); //将key插入二叉排序树T scanf("%d",&key);//读人下一关键字 } return T; //返回建立的二叉排序树的根指针 } //BSTree ⑤二叉排序树的生成过程 由输入实例(5,3,7,2,4,8),根据生成二叉排序树算法生成二叉排序树的过程【参见动画演示】 注意: 输入序列决定了二叉排序树的形态。 二叉排序树的中序序列是一个有序序列。所以对于一个任意的关键字序列构造一棵二叉排序树,其实质是对此关键字序列进行排序,使其变为有序序列。"排序树"的名称也由此而来。通常将这种排序称为树排序(Tree Sort),可以证明这种排序的平均执行时间亦为O(nlgn)。 对相同的输入实例,树排序的执行时间约为堆排序的2至3倍。因此在一般情况下,构造二叉排序树的目的并非为了排序,而是用它来加速查找,这是因为在一个有序的集合上查找通常比在无序集合上查找更快。因此,人们又常常将二叉排序树称为二叉查找树。 (2)二叉排序树的删除 从二叉排序树中删除一个结点,不能把以该结点为根的子树都删去,并且还要保证删除后所得的二叉树仍然满足BST性质。 ①删除操作的一般步骤 (1) 进行查找 查找时,令p指向当前访问到的结点,parent指向其双亲(其初值为NULL)。若树中找不到被删结点则返回,否则被删结点是*p。 (2) 删去*p。 删*p时,应将*p的子树(若有)仍连接在树上且保持BST性质不变。按*p的孩子数目分三种情况进行处理。 ②删除*p结点的三种情况 (1)*p是叶子(即它的孩子数为0) 无须连接*p的子树,只需将*p的双亲*parent中指向*p的指针域置空即可。 (2)*p只有一个孩子*child 只需将*child和*p的双亲直接连接后,即可删去*p。 注意: *p既可能是*parent的左孩子也可能是其右孩子,而*child可能是*p的左孩子或右孩子,故共有4种状态,具体【参见动画演示】。 (3)*p有两个孩子 先令q=p,将被删结点的地址保存在q中;然后找*q的中序后继*p,并在查找过程中仍用parent记住*p的双亲位置。*q的中序后继*p一定是*q的右子树中最左下的结点,它无左子树。因此,可以将删去*q的操作转换为删去的*p的操作,即在释放结点*p之前将其数据复制到*q中,就相当于删去了*q。具体【参见动画演示】。 ③二叉排序树删除算法 分析: 上述三种情况都能统一到情况(2),算法中只需针对情况(2)处理即可。 注意边界条件:若parent为空,被删结点*p是根,故删去*p后,应将child置为根。 算法: void DelBSTNode(BSTree *Tptr,KeyType key) {//在二叉排序树*Tptr中删去关键字为key的结点 BSTNode *parent=NUll,*p=*Tptr,*q,*child; while(p){ //从根开始查找关键字为key的待删结点 if(p->key==key) break;//已找到,跳出查找循环 parent=p; //parent指向*p的双亲 p=(key if(!p) return; //找不到被删结点则返回 q=p; //q记住被删结点*p if(q->lchild&&q->rchild) //*q的两个孩子均非空,故找*q的中序后继*p for(parent=q,p=q->rchild; p->lchild; parent=p,p=p=->lchild); //现在情况(3)已被转换为情况(2),而情况(1)相当于是情况(2)中child=NULL的状况 child=(p->lchild)?p->lchild:p->rchild;//若是情况(2),则child非空;否则child为空 if(!parent) //*p的双亲为空,说明*p为根,删*p后应修改根指针 *Tptr=child; //若是情况(1),则删去*p后,树为空;否则child变为根 else{ //*p不是根,将*p的孩子和*p的双亲进行连接,*p从树上被摘下 if(p==parent->lchild) //*p是双亲的左孩子 parent->lchild=child; //*child作为*parent的左孩子 else parent->rchild=child; //*child作为 parent的右孩子 if(p!=q) //是情况(3),需将*p的数据复制到*q q->key=p->key; //若还有其它数据域亦需复制 } //endif free(p); /释放*p占用的空间 } //DelBSTNode 二叉排序树的删除运算实例具体参见【动画演示】 (3)二叉排序树上的查找 ①查找递归算法 在二叉排序树上进行查找,和二分查找类似,也是一个逐步缩小查找范围的过程。 递归的查找算法: BSTNode *SearchBST(BSTree T,KeyType key) { //在二叉排序树T上查找关键字为key的结点,成功时返回该结点位置,否则返回NUll if(T==NULL||key==T->key) //递归的终结条件 return T; //T为空,查找失败;否则成功,返回找到的结点位置 if(key return SearchBST(T->lchild,key); else return SearchBST(T->rchild,key);//继续在右子树中查找 } //SearchBST ②算法分析 在二叉排序树上进行查找时,若查找成功,则是从根结点出发走了一条从根到待查结点的路径。若查找不成功,则是从根结点出发走了一条从根到某个叶子的路径。 (1) 二叉排序树查找成功的平均查找长度 在等概率假设下,下面(a)图中二叉排序树查找成功的平均查找长度为 在等概率假设下,(b)图所示的树在查找成功时的平均查找长度为: ASL b=(1+2+3+4+5+6+7+8+9+10)/10=5.5 注意: 与二分查找类似,和关键字比较的次数不超过树的深度。 (2)在二叉排序树上进行查找时的平均查找长度和二叉树的形态有关 二分查找法查找长度为n的有序表,其判定树是惟一的。含有n个结点的二叉排序树却不惟一。对于含有同样一组结点的表,由于结点插入的先后次序不同,所构成的二叉排序树的形态和深度也可能不同 【例】下图(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)二叉排序树和二分查找的比较 就平均时间性能而言,二叉排序树上的查找和二分查找差不多。 就维护表的有序性而言,二叉排序树无须移动结点,只需修改指针即可完成插入和删除操作,且其平均的执行时间均为O(lgn),因此更有效。二分查找所涉及的有序表是一个向量,若有插入和删除结点的操作,则维护表的有序性所花的代价是O(n)。当有序表是静态查找表时,宜用向量作为其存储结构,而采用二分查找实现其查找操作;若有序表里动态查找表,则应选择二叉排序树作为其存储结构。 (4)平衡二叉树 为了保证二叉排序树的高度为lgn,从而保证然二叉排序树上实现的插入、删除和查找等基本操作的平均时间为O(lgn),在往树中插入或删除结点时,要调整树的形态来保持树的"平衡。使之既保持BST性质不变又保证树的高度在任何情况下均为O(lgn),从而确保树上的基本操作在最坏情况下的时间均为O(lgn)。 注意: ①平衡二叉树(Balanced Binary Tree)是指树中任一结点的左右子树的高度大致相同。 ②任一结点的左右子树的高度均相同(如满二叉树),则二叉树是完全平衡的。通常,只要二叉树的高度为O(1gn),就可看作是平衡的。 ③平衡的二叉排序树指满足BST性质的平衡二叉树。 ④AVL树中任一结点的左、右子树的高度之差的绝对值不超过1。在最坏情况下,n个结点的AVL树的高度约为1.44lgn。而完全平衡的二叉树度高约为lgn,AVL树是接近最优的。 //二叉树的基本操作 #include 二叉树的基本操作实现及其应用 一、实验目的 1.熟悉二叉树结点的结构和对二叉树的基本操作。 2.掌握对二叉树每一种操作的具体实现。 3.学会利用递归方法编写对二叉树这种递归数据结构进行处理的算法。 4.会用二叉树解决简单的实际问题。 二、实验内容 设计程序实现二叉树结点的类型定义和对二叉树的基本操作。该程序包括二叉树结构类型以及每一种操作的具体的函数定义和主函数。 1 按先序次序建立一个二叉树, 2按(A:先序 B:中序 C:后序)遍历输出二叉树的所有结点 以上比做,以下选做 3求二叉树中所有结点数 4求二叉树的深度 三、实验步骤 ㈠、数据结构与核心算法的设计描述 /* 定义DataType为char类型 */ typedef char DataType; /* 二叉树的结点类型 */ typedef struct BitNode { DataType data; struct BitNode *lchild,*rchild; }*BitTree; 相关函数声明: 1、/* 初始化二叉树,即把树根指针置空 */ void BinTreeInit(BitTree *BT) { BT=(BitTree)malloc(sizeof(BitNode)); BT->data=NULL; cout<<"二叉树初始化成功!"< /*实验三:二叉树遍历操作验证*/ #include if(T) //若非空 { if(T->data) { //输出 printf("%c",T->data); } preOrderTraverse(T->lchild); preOrderTraverse(T->rchild); } } //递归方法中序遍历二叉树 void inOrderTraverse(BiTree T) { if(T) //若非空 { preOrderTraverse(T->lchild); if(T->data) { //输出 printf("%c",T->data); } preOrderTraverse(T->rchild); } } //递归方法后序遍历二叉树 void postOrderTraverse(BiTree T) { if(T) //若非空 { preOrderTraverse(T->lchild); preOrderTraverse(T->rchild); if(T->data) { //输出 printf("%c",T->data); } } } //层序遍历二叉树 void LevelTraverse(BiTree T) { queue 实验三二叉树的基本运算 一、实验目的 1、使学生熟练掌握二叉树的逻辑结构和存储结构。 2、熟练掌握二叉树的各种遍历算法。 二、实验内容 题目一:二叉树的基本操作实现(必做题) [问题描述] 建立一棵二叉树,试编程实现二叉树的如下基本操作: 1. 按先序序列构造一棵二叉链表表示的二叉树T; 2. 对这棵二叉树进行遍历:先序、中序、后序以及层次遍历,分别输出结点的遍历序列; 3. 求二叉树的深度/结点数目/叶结点数目;(选做) 4. 将二叉树每个结点的左右子树交换位置。(选做) [基本要求] 从键盘接受输入(先序),以二叉链表作为存储结构,建立二叉树(以先序来建立), [测试数据] 如输入:ABCффDEфGффFффф(其中ф表示空格字符) 则输出结果为 先序:ABCDEGF 中序:CBEGDFA 后序:CGEFDBA 层序:ABCDEFG [选作内容] 采用非递归算法实现二叉树遍历。 三、算法设计 1、主要思想:根据二叉树的图形结构创建出二叉树的数据结构,然后 用指针对树进行操作,重点掌握二叉树的结构和性质。 2、本程序包含四个模块: (1)结构体定义 (2)创建二叉树 (3)对树的几个操作 (4)主函数 四、调试分析 这是一个比较简单程序,调试过程中并没有出现什么问题,思路比较清晰 五、实验结果 六、总结 此次上机实验对二叉树进行了以一次实际操作,让我对二叉树有了更深的了解,对二叉树的特性有了更熟悉的认知,让我知 道了二叉树的重要性和便利性,这对以后的编程有更好的帮助。 七、源程序 #include 二叉树的基本操作及实现 二叉树的基本操作及实现的代码如下: #include 数据结构二叉树基本操作 (1). // 对二叉树的基本操作的类模板封装 //------------------------------------------------------------------------------------------------------------------------ #include 班级:数媒1101 学号:0305110125 课程名称:数据结构实验 实验名称:二叉树及其操作的实现 实验内容和目的: 内容:1. 创建二叉树; 2. 用递归方法实现二叉树的各种遍历。 目的:1.掌握二叉树的定义和存储表示,学会建立一棵特定二叉树的方法; 2.掌握二叉树的遍历算法(先序、中序、后序遍历算法)的思想,并学会遍 历算法的递归实现和非递归实现。 实验步骤: 1.首先定义二叉树的存储形式; 2.用CreateBiTree( )构造二叉链表表示的二叉树T; 3. 用PreOrder ( bitree *t )、InOrder ( bitree *t)、PostOrder ( bitree * t )这三个函数 对二叉树依次进行先序、中序、后序遍历,并输出遍历序列。 实验代码/文件描述: #include "stdio.h" #include "stdlib.h" #define maxsize 64 #define null 0 typedef char datatype; typedef struct node { datatype data; struct node * lchild, * rchild; } bitree; bitree * bitr; bitree *Q[maxsize]; bitree *CREATREE( ) { char ch ; int front , rear ; bitree *root , *s ; root = null ; front = 1 ; rear = 0 ; ch = getchar( ) ; while ( ch != '#' ) { s = null ; if ( ch != '@' ) { s =(bitree*) malloc(sizeof(bitree)); s->data = ch ; s->lchild = null ;s->rchild =null; } rear ++; Q[rear] = s ; if (rear == 1 ) root = s ; else { if ( s && Q[front] ) if (rear%2==0 ) Q[front]->lchild = s ; else Q[front]->rchild = s ; if ( rear%2==1 ) front ++; } ch = getchar ( ) ; } return root ; } void PreOrder ( bitree *t ) { if ( t != null ) { printf("\t%c\n",t->data); PreOrder ( t->lchild ); PreOrder ( t->rchild ); } } void InOrder ( bitree *t) { if ( t != NULL ) { InOrder ( t->lchild ); printf("\t%c\n", t->data); InOrder ( t->rchild ); } } 《数据结构与数据库》 实验报告 实验题目 二叉树的基本操作及运算 一、需要分析 问题描述: 实现二叉树(包括二叉排序树)的建立,并实现先序、中序、后序和按层次遍历,计算叶子结点数、树的深度、树的宽度,求树的非空子孙结点个数、度为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、进一步掌握递归算法的设计方法。 二.实验内容 1、按照下面二叉树二叉链表的存储表示,编写头文件binary_tree.h,实现二叉链表的定义与基本操作实现函数;编写主函数文件test10.cpp,验证头文件中各个操作。 二叉树二叉链表存储表示如下: typedef struct BiTNode { TElemType data ; struct BiTNode *lchild , *rchild ; }BiTNode,*BiTree ; 基本操作如下: ①void InitBiTree(BiTree &T ) //初始化二叉树T ②void CreateBiTree(BiTree &T) //按先序遍历序列建立二叉链表T ③bool BiTreeEmpty (BiTree T); //检查二叉树T是否为空,空返回1,否则返回0 ④int BiTreeDepth(BiTree T); //求二叉树T的深度并返回该值 ⑤void PreOrderTraverse (BiTree T); //先序遍历二叉树T ⑥void InOrderTraverse (BiTree T); //中序遍历二叉树T ⑦void PostOrderTraverse (BiTree T); //后序遍历二叉树T ⑧void DestroyBiTree(BiTree &T) //销毁二叉树T 实验四-二叉树操作实现 实验四二叉树操作实现 实验日期:2017 年 4 月20 日 实验目的及要求 1. 熟练掌握树的基本概念、二叉树的基本操作及在链式存储结构上的实现; 2. 重点掌握二叉树的创建、遍历及求深度等算法; 3. 掌握运用递归方式描述算法及编写递归C程序的方法,提高算法分析和程序设计能力。 实验内容 键盘输入一个字符串,利用二叉树前序遍历的结果建成一棵二叉树,并用三种遍历方法打印,比较是否与自己预先想象的相一致。再求树的深度、1度结点数、2度节点数,交换二叉树的左右子树并输出交换后的中序遍历结果验证交换的正确性。找到二叉树中序遍历最后一个结点并输出结点值。 二叉树结点类型定义: typedef char datatype; typedef struct tnode{ datatype data; struct tnode *lchild,*rchild; } BiTNode,*BiTree; 任务 1.题目要求 创建一个程序文件sy4.cpp,自定义相应函数完成以下操作: (1)void visit(BiTree p) /*输出p指针指向的结点*/ (2)void Preorder(BiTree T) /*前序遍历*/ (3)void Inorder(BiTree T) /*中序遍历*/ (4)void Postorder(BiTree T) /*后序遍历*/ (5)BiTree CreateTree( ) /*以前序遍历的顺序建立二叉树*/ (6)int deep(BiTree T) /*求二叉树深度*/ (7)int leaf(BiTree T) /*求叶子结点数*/ (8)int OneChild(BiTree T) /*求1度结点数*/ (9)int TwoChild(BiTree T) /*求2度结点数*/ (10)void Exchange(BiTree T) /*二叉树左右子树交换*/ (11)BiTree InorderLastNode(BiTree T); /*找二叉树中序遍历最后一个结点*/ 2.请回答下列问题 (1)在n个结点二叉树的二叉链表存储中,其指针域的总数为2n 个,其中n-1 个用于链接孩子结点,n+1 个空闲着。 (2)在二叉链表存储中,数据域值为data,左右子树的指针分别为left和right,则判断: 指针p所指结点为0度结点的条件是p->left==NULL&&p->right==NULL ;指针p所指结点为1度结点的条件是(p->left==NULL&&p->right!=NULL)||(p->left!=NULL&&p->right==NULL) ; 指针p所指结点为2度结点的条件是p->left!=NULL&&p->right!=NULL 。(3)T为二叉树的根的地址,该树是空二叉树满足条件:T==NULL 。 3.sy14.cpp源程序清单(含必要的注释) #include 本程序由SOGOF完成 该完整程序主要是递归函数的使用及模板的使用,完成了对二叉树基本的链表操作,主要有二叉树的建立,前序、中序、后序遍历,求树的高度,每层结点数(包含树的最大宽度),左右结点对换,二叉树的内存释放,求解树的叶子数。 #include 创作编号: GB8878185555334563BT9125XW 创作者:凤呜大王* //二叉树的基本操作 #include cout<<"--------------请选择------------"< 数据结构程序报告(平衡二叉树的操作) 计算机科学学院数据结构课程设计报告 平衡二叉树操作 学生姓名: 学号: 班级: 指导老师: 报告日期: 1.需求分析 1.建立平衡二叉树并进行创建、查找、插入、删除等功能。 2.设计一个实现平衡二叉树的程序,可进行创建、查找、插入、删除等操作,实现动态的输入数据,实时的输出该树结构。 3.测试数据:自选数据 2.概要设计 1.抽象数据类型定义: typedef struct BSTNode { int data; int bf; //节点的平衡因子 struct BSTNode *lchild,*rchild; //左右孩子指针 }BSTNode,*BSTree; void CreatBST(BSTree &T); //创建平衡二叉树 void R_Rotate(BSTree &p); //对以*p 为根的二叉排序树作左旋处理 void L_Rotate(BSTree &p); //对以*p 为根的二叉排序树作左旋处理 void LeftBalance(BSTree &T); //对以指针T所指结点为根的二叉树作左平衡旋转处理void RightBalance(BSTree &T); //对以指针T所指结点为根的二叉树作右平衡旋转处理bool InsertA VL(BSTree &T,int e,bool &taller); //插入结点e bool SearchBST(BSTree &T,int key); //查找元素key是否在树T中 void LeftBalance_div(BSTree &p,int &shorter); void RightBalance_div(BSTree &p,int &shorter); ******************************* 实验题目:二叉树的操作 实验者信息:班级 13007102,姓名 庞文正,学号 1300710226 实验完成的时间 3:00 ****************************** 一、 实验目的 1, 掌握二叉树链表的结构和二叉树的建立过程。 2, 掌握队列的先进先出的运算原则在解决实际问题中的应用。 3, 进一步掌握指针变量、指针数组、动态变量的含义。 4, 掌握递归程序设计的特点和编程方法。 二、 实验内容 已知以二叉链表作存储结构,试编写按层次遍历二叉树的算法。 (所谓层次遍历,是 指从二叉树的根结点开始从上到下逐层遍历二叉树, 在同一层次中从左到右依次访问各个节 点。)调试程序并对相应的输出作出分析;修改输入数据,预期输出并验证输出的结果。加 深对算法的理解。 三、 算法设计与编码 1. 本实验用到的理论知识 总结本实验用到的理论知识, 实现理论与实践相结合。 总结尽量简明扼要, 并与本次实验密 切相关,最好能加上自己的解释。 本算法要采用一个循环队列 que,先将二叉树根结点入队列,然后退队列,输出该 结点;若它 有左子树,便将左子树根结点入队列; 若它有右子树,便将右子树根结点入队列, 直到队列空为止。因为队列的特点是先进先出,从而达到按层次顺序遍历二叉的目的。 2. 算法概要设计 给出实验的数据结构描述,程序模块、功能及调用关系 #include 二叉树的创建与遍历 一、实验目的 1.学会实现二叉树结点结构和对二叉树的基本操作。 2.掌握对二叉树每种操作的具体实现,学会利用递归和非递归方法编写对二叉树这种递归数据结构进行处理的算法。 二、实验要求 1.认真阅读和掌握和本实验相关的教材内容。 2.编写完整程序完成下面的实验内容并上机运行。 3.整理并上交实验报告。 三、实验内容 1.编写程序任意输入二叉树的结点个数和结点值,构造一棵二叉树,采用三种递归和非递归遍历算法(前序、中序、后序)对这棵二叉树进行遍历。 四、实验步骤 源程序代码1 #include 二叉树的基本操作 摘要: 本次课程设计通过对二叉树的一系列操作主要练习了二叉树的建立、四种遍历方式:先序遍历、中序遍历、后序遍历和层序遍历以及节点数和深度的统计等算法。增加了对二叉树这一数据结构的理解,掌握了使用c语言对二叉树进行一些基本的操作。 关键字:递归、二叉树、层序遍历、子树交换 一、程序简介 本程序名为“二叉树基本操作的实现”,其主要为练习二叉树的基本操作而开发,其中包含了建立、遍历、统计叶子结点和深度等一系列操作。其中定义二叉链表来表示二叉树,用一个字符类型的数据来表示每一个节点中存储的数据。由于没有进行图形界面的设计,用户可以通过程序中的遍历二叉树一功能来查看操作的二叉树。 二、功能模块 2.1功能模块图 2.2功能模块详解 2.2.1建立二叉树 输入要建立的二叉树的扩展二叉树的先序遍历序列,来建立二叉树,建立成功会给出提示。 2.2.2遍历二叉树 执行操作之后会有四个选项可供选择:先序遍历、中序遍历、后序遍历、层序遍历。 输入对应的序号即可调动相关函数输出相应的遍历序列。 2.2.3统计叶子节点树 执行之后输出叶子结点的个数。 2.2.4求二叉树深度 执行之后输出二叉树的深度。 2.2.5子树交换 交换成功则会给出提示,用户可通过遍历二叉树来观察子树交换之后的二叉树。 三、数据结构和算法设计 3.1二叉链表的设计 1.typedef struct BiNode { 2.char data; 3.struct BiNode* lchild; //左孩子 4.struct BiNode* rchild; //右孩子 5.}BiTree; 用一个字符型保存节点数据,分别定义两个struct BiNode类型的指针来指向左孩子和右孩子。在BiTree.h中实现相关的功能。 3.2队列的实现 1.typedef struct { 2. ElemType* data; 3.int head;//队头指针 4.int tail;//队尾指针 5.} SqQueue; 队列主要用于二叉树遍历过程中的层序遍历,从根节点开始分别将左右孩子放入队列,然后从对头开始输出。队列的相关操作封装在SqQueue.h中,包括入队、出队、判断队列是否为空等操作。 二叉树操作的实现 实验目的与要求: 1.基础知识:掌握数据结构中二叉树的相关知识;掌握C或VC++语言中程序设计的方法. 2.参考教材相关算法,完成以下程序功能: (1) 能够采用二叉链存储,并实现二叉树的建立; (2)完成已建立的二叉树的三种遍历; (3)完成二叉树中特定结点的统计,如0元素结点或叶子结点统计; (4)程序中有友好的操作设计. 实验性质:验证性(2学时) 说明:程序包含主要函数:主函数、操作界面、建树、独立的三种遍历、特定结点统计、相关注释,注意在主函数流程中体现先建树后遍历和特定结点统计的条件 #include int j=0; int *g=&j; void shuru(node*&t,char sn[50]) { char ch; ch=sn[j++]; if(ch=='@') printf("输入的二叉树有误建树失败\n"); else if(ch=='#')t=NULL; else { t=(node*)malloc(sizeof(node)); t->data=ch; shuru(t->lchild,sn); shuru(t->rchild,sn); }} void xianxu(node*&t) { if(t!=NULL) { printf("%c",t->data); xianxu(t->lchild); xianxu(t->rchild); }} void zhongxu(node*&t) { if(t!=NULL) { zhongxu(t->lchild); printf("%c",t->data); zhongxu(t->rchild); }} void houxu(node *&t) { if(t!=NULL) 二叉树的基本操作实验报告 学号姓名实验日期 2012-12-26 实验室计算机软件技术实验指导教师设备编号 401 实验内容二叉树的基本操作 一实验题目 实现二叉树的基本操作的代码实现 二实验目的 1、掌握二叉树的基本特性 2、掌握二叉树的先序、中序、后序的递归遍历算法 3、通过求二叉树的深度、度为2的结点数和叶子结点数等算法三实习要求 (1)认真阅读书上给出的算法 (2)编写程序并独立调试 四、给出二叉树的抽象数据类型 ADT BinaryTree{ //数据对象D:D是具有相同特性的数据元素的集合。 //数据关系R: // 若D=Φ,则R=Φ,称BinaryTree为空二叉树; // 若D?Φ,则R={H},H是如下二元关系; // (1)在D中存在惟一的称为根的数据元素root,它在关系H下无前驱; // (2)若D-{root}?Φ,则存在D-{root}={D1,Dr},且D1?Dr =Φ; // (3)若D1?Φ,则D1中存在惟一的元素x1, // (4)(D1,{H1})是一棵符合本定义的二叉树,称为根的左子树;(Dr,{Hr})是一棵符合本定义的二叉树,称为根的右子树。 //基本操作: CreateBiTree( &T, definition ) // 初始条件:definition给出二叉树T的定义。 // 操作结果:按definiton构造二叉树T。 BiTreeDepth( T ) // 初始条件:二叉树T存在。 // 操作结果:返回T的深度。 PreOrderTraverse( T, visit() ) // 初始条件:二叉树T存在,Visit是对结点操作的应用函数。 // 操作结果:先序遍历T,对每个结点调用函数Visit一次且仅一次。一旦visit()失败,则操 作失败。 InOrderTraverse( T, visit() ) // 初始条件:二叉树T存在,Visit是对结点操作的应用函数。 // 操作结果:中序遍历T,对每个结点调用函数Visit一次且仅一次。一旦visit()失败,则操 作失败。 PostOrderTraverse( T, visit() ) // 初始条件:二叉树T存在,Visit是对结点操作的应用函数。 // 操作结果:后序遍历T,对每个结点调用函数Visit一次且仅一次。一旦visit()失败,则操 作失败。 LeafNodes(p) // 初始条件:二叉树T存在。 // 操作结果:返回T的叶子结点数。 #include "stdio.h" #include "stdlib.h" #include "string.h" #include "math.h" typedef char TElemType; //定义结点数据为字符型 typedef int Status; //定义函数类型为 int 型 #define ERROR 0 #define OK 1 }BiTNode, *BiTree; Status NumJudge(char ch[20]){ //限制输入数据必须为大于零的整形 char ch1[20]; int num; while(1){ scanf("%s",ch); num=atoi(ch); // 将字符串转换为整型 itoa(num,ch1,10); //将整型转换为字符串型 if(strcmp(ch,ch1)==0&&num>0)break; else{printf(" 请输入一个大于零的整数 : ");} } return num; }//NumJudge Status InitBiTree(BiTree &T){ //构造空二叉树 T if(!(T=(BiTree)malloc(sizeof(BiTNode))))exit(ERROR); T->next=NULL; printf("\n\t 空二叉树构建成功 !\n\n"); return OK; }//InitBiTree Status DestroyTree(BiTree &T,BiTree t){ //销毁二叉树 if(T){ free(T);T=NULL; printf ("\t 二叉树销毁成功 !\n"); } if(t){ DestroyTree(T,t->lchild); DestroyTree(T,t->rchild); free(t); } return OK; }//DestroyTree Status ClearBiTree(BiTree &T,int sum,int &i){ //清空二叉树 if(T){ typedef struct BiTNode{ //定义结构 体 TElemType data; // 结点数值 struct BiTNode *lchild; // 左孩子指针 struct BiTNode *rchild; // 右孩子指针 struct BiTNode *next; //下一结点指针 //若申请空间失败则退出二叉树的基本 操作
实验三 二叉树的基本操作实现及其应用
数据结构——二叉树的操作(遍历及树形输出)
实验三二叉树的基本操作
二叉树的基本操作及实现.cpp
数据结构——二叉树基本操作源代码
二叉树及其操作的实现
数据结构实验三——二叉树基本操作及运算实验报告
实验10 二叉树的基本操作
实验四-二叉树操作实现
二叉树基本操作经典实例
二叉树的基本 操作
数据结构程序报告(平衡二叉树的操作)
数据结构实验-二叉树的操作
C++二叉树的创建与遍历实验报告
数据结构课程设计-二叉树的基本操作
二叉树操作的实现
二叉树的基本操作实验报告
二叉树的基本操作完整版,包含二叉树的所有操作,凡是你想要的都在里面