数据结构程序报告(平衡二叉树的操作)

合集下载

数据结构二叉树实验报告

数据结构二叉树实验报告

一 、实验目的和要求(1)掌握树的相关概念,包括树、节点的度、树的度、分支节点、叶子节点、孩子节点、双亲节 点、树的深度、森林等定义。

(2)掌握树的表示,包括树形表示法、文氏图表示法、凹入表示法和括号表示法等。

(3)掌握二叉树的概念,包括二叉树、满二叉树和完全二叉树的定义。

(4)掌握二叉树的性质。

(5)重点掌握二叉树的存储结构,包括二叉树顺序存储结构和链式存储结构。

(6)重点掌握二叉树的基本运算和各种遍历算法的实现。

(7)掌握线索二叉树的概念和相关算法的实现。

(8)掌握哈夫曼树的定义、哈夫曼树的构造过程和哈夫曼编码的产生方法。

(9)掌握并查集的相关概念和算法。

(10)灵活运用二叉树这种数据结构解决一些综合应用问题。

二、实验内容注:二叉树b 为如图7-123所示的一棵二叉树图7-123+实验7.1 编写一个程序algo7-1.cpp,实现二叉树的各种运算,并在此基础上设计一个程序exp7-1.cpp 完成如下功能:(1)输出二叉树b ;(2)输出H 节点的左、右孩子节点值; (3)输出二叉树b 的深度; (4)输出二叉树b 的宽度; (5)输出二叉树b 的节点个数;(6)输出二叉树b 的叶子节点个数。

实验7.2设计一个程序exp7-2.cpp,实现二叉树的先序遍历、中序遍历和后序遍历和非递归算法, 以及层次变量里的算法。

并对图7-123所示的二叉树b 给出求解结果。

b+ACF GIKL+NM+E+HdJD₄B臣1607-1.CPPif(b?-HULL)re3P4+;Qu[rear]-p-b;Qu[rear].1no=1;while(reart=front){Front++;b=Qu[front]-P;lnum-Qu[front].1no;if(b->Ichildt=NULL)rpar+t;Qu[rear]-p=b->1child;Qu[rear].Ino-lnun+1;if(D->rch11d?=NULL)1/根结点指针入队//根结点的层次编号为1 1/队列不为空1/队头出队1/左孩子入队1/右孩子入队redr+t;qu[rear]-p=b->rchild;Qu[rear].1no-lnun*1;}}nax-0;lnun-1;i-1;uhile(i<=rear){n=0;whdle(i<=rear ge Qu[1].1no==1num)n+t;it+;Inun-Qu[i].1n0;if(n>max)nax=n;}return max;田1607-1.CPPreturn max;}elsereturn o;口×int Modes(BTNode *D) //求二叉树D的结点个数int nun1,nun2;if(b==NULL)returng,else if(b->ichild==NULL&D->rchild==NULL)return 1;else{num1-Hodes(b->Ichild);num2=Nodes(b->rchild);return(num1+nun2+1);LeafNodes(BINode *D) //求二叉树p的叶子结点个数int num1,num2;1f(D==NULL)return 0;else if(b->1chi1d==NULLc& b->rch11d==NULL)return 1;else{num1-LeafModes(b->lchild);num2=LeafNodes(b->rchild);return(nun1+nun2);int程序执行结果如下:xCProrn FlslirosfViu l SudiollyPrjecslro7 LJebuglFoj7 ex<1)输出二叉树:A<B<D,E<H<J,K<L,M<,N>>>>),C<F,G<,I>>)<2)'H’结点:左孩子为J石孩子为K(3)二叉树b的深度:7<4)二叉树b的宽度:4(5)二叉树b的结点个数:14(6)二叉树b的叶子结点个数:6<?>释放二叉树bPress any key to continue实验7 . 2程序exp7-2.cpp设计如下:坠eTPT-2.EPP#include<stdio.h》winclude<malloc.h>deFn Masie 00typde chr ElemTyetypede sruct nde{ElemType data;stuc node *lclldstruct node rchild;》BTHode;extern vod reaeBNodeBTNode extrn void DispBTHode(BTNodeuoid ProrderBTNode *b)if(b?-NULL)- 回1 / 数据元素1 / 指向左孩子1 / 指向右孩子*eb car *str)xb1 / 先序遍历的递归算法1 / 访问根结点/ / 递归访问左子树1 7 递归访问右子树/ / 根结点入栈//栈不为空时循环/ / 退栈并访问该结点/ / 右孩子入栈{》v oidprintf(*c“,b->data); Preorder(b->lchild); Pre0rder(b->rchild);Preorder1(BTNode *b)BTNode xSt[Maxsize],*p;int top=-1;if(b!-HULL)top++;St[top]-b;uhle (op>-)p-St[top];top--;printf("%c“,p->data);if(p->rchild?-HULL)A约e程p7-2.CPPprintF(”后序逅历序列:\n");printf(" 递归算法=");Postorder(b);printf("\n");printf(“非递归算法:“);Postorder1(b);printf("\n");序执行结果如下:xCAPrograFleicsoftVisal SudlyrjecsProj 2Debuzlroj72ex"二叉树b:A(B(D,ECH<J,K(L,M<,N)>))),C(F,GC.I>))层次遍历序列:A B C D E F G H I J K L M N先序遍历序列:递归算法:A B D E H J K L M N C F G I非归算法:A B D E H J K L M N C F G I中序遍历序列:递归算法: D B J H L K M N E A F C G I非递归算法:D B J H L K M N E A F C G I后序遍历序列:递归算法: D J L N M K H E B F I G C A非递归算法:D J L N H K H E B F I G C APress any key to continue臼p7-3.CPP15Pp a t h[p a t h l e n]-b->d a t a;//将当前结点放入路径中p a t h l e n t+;/7路任长度培1Al1Path1(b->ichild,patn,pathlen);1/递归扫描左子树Al1Path1(b->rchild,path,pathlen); //递归扫描右子树pathlen-- ; //恢复环境uoid Longpath(BTNode *b,Elemtype path[1,int pathlen,Elemtype longpath[],int elongpatnien) int i;1f(b==NULL){if(pathlen>longpatnlen) //若当前路径更长,将路径保存在1ongpatn中for(i-pathlen-1;i>-8;i--)longpath[i]=path[1];longpathlen-pathlen;elsepath[pathlen]=b->data; pathlen4; //将当前结点放入路径中//路径长度增1iongPath(b->lchild,path₇pathlen,langpath,longpathien);//递归扫描左子树LongPath(b->rchiid,path,pathien,longpath,longpathien);//递归扫描石子树pathlen--; /7饮其环境oid DispLeaf(BTNode xb)- 口凶uoid DispLeaf(BTNode xb)iE(D!=NULL){ if(b->1child--HULL B& b->rchild--HULL)printf("3c“,b->data);elsepispLeaf(b->ichild);DispLeaf(b->rchild);oid nain()8TNodexb;ElenType patn[Maxsize],longpath[Maxsize];int i.longpathien-U;CreateBTNode(b,"A(B(D,E(H(J,K(L,H(,N))))),C(F,G(,I)))");printf("\n二灾树b:");DispBTNode(b);printf("\n\n*);printf(”b的叶子结点:");DispLeaf(b);printf("\n\n");printf("A11Path:");A11Path(b);printf("m");printf("AiiPath1:n");AliPath1(b.path.);printf("");LongPath(b,path,8,longpath,longpathlen);printf(”第一条量长路径长度=d\n”,longpathlen);printf(”"第一茶最长路径:");for(i=longpathlen;i>=0;i--)printf("c",longpatn[1]);printf("\n\n");。

数据结构实验报告(四)

数据结构实验报告(四)

《数据结构》实验报告班级:学号:姓名:实验四二叉树的基本操作实验环境:Visual C++实验目的:1、掌握二叉树的二叉链式存储结构;2、掌握二叉树的建立,遍历等操作。

实验内容:通过完全前序序列创建一棵二叉树,完成如下功能:1)输出二叉树的前序遍历序列;2)输出二叉树的中序遍历序列;3)输出二叉树的后序遍历序列;4)统计二叉树的结点总数;5)统计二叉树中叶子结点的个数;实验提示://二叉树的二叉链式存储表示typedef char TElemType;typedef struct BiTNode{TElemType data;struct BiTNode *lchild,*rchild;}BiTNode,*BiTree;一、程序源代码#include <stdio.h>#include <stdlib.h>#define MAXSIZE 30typedef char ElemType;typedef struct TNode *BiTree;struct TNode {char data;BiTree lchild;BiTree rchild;};int IsEmpty_BiTree(BiTree *T) { if(*T == NULL)return 1;elsereturn 0;}void Create_BiTree(BiTree *T){char ch;ch = getchar();//当输入的是"#"时,认为该子树为空if(ch == '#')*T = NULL;//创建树结点else{*T = (BiTree)malloc(sizeof(struct TNode)); (*T)->data = ch; //生成树结点//生成左子树Create_BiTree(&(*T)->lchild);//生成右子树Create_BiTree(&(*T)->rchild);}}void TraverseBiTree(BiTree T) { //先序遍历if(T == NULL)return;else {printf("%c ",T->data);TraverseBiTree(T->lchild);TraverseBiTree(T->rchild);}}void InOrderBiTree(BiTree T) { //中序遍历if(NULL == T)return;else {InOrderBiTree(T->lchild);printf("%c ",T->data);InOrderBiTree(T->rchild);}}void PostOrderBiTree(BiTree T) {if(NULL == T)return;else {InOrderBiTree(T->lchild);InOrderBiTree(T->rchild);printf("%c ",T->data);}}int TreeDeep(BiTree T) {int deep = 0;if(T){int leftdeep = TreeDeep(T->lchild);int rightdeep = TreeDeep(T->rchild);deep = leftdeep+1 > rightdeep+1 ? leftdeep+1 : rightdeep+1;}return deep;}int Leafcount(BiTree T, int &num) {if(T){if(T->lchild ==NULL && T->rchild==NULL){num++;printf("%c ",T->data);}Leafcount(T->lchild,num);Leafcount(T->rchild,num);}return num;}void LevelOrder_BiTree(BiTree T){//用一个队列保存结点信息,这里的队列采用的是顺序队列中的数组实现 int front = 0;int rear = 0;BiTree BiQueue[MAXSIZE];BiTree tempNode;if(!IsEmpty_BiTree(&T)){BiQueue[rear++] = T;while(front != rear){//取出队头元素,并使队头指针向后移动一位tempNode = BiQueue[front++];//判断左右子树是否为空,若为空,则加入队列 if(!IsEmpty_BiTree(&(tempNode->lchild))) BiQueue[rear++] = tempNode->lchild;if(!IsEmpty_BiTree(&(tempNode->rchild))) BiQueue[rear++] = tempNode->rchild;printf("%c ",tempNode->data);}}}int main(void){BiTree T;BiTree *p = (BiTree*)malloc(sizeof(BiTree));int deepth,num=0 ;Create_BiTree(&T);printf("先序遍历二叉树:\n");TraverseBiTree(T);printf("\n");printf("中序遍历二叉树:\n");InOrderBiTree(T);printf("\n");printf("后序遍历二叉树:\n");PostOrderBiTree(T);printf("\n层次遍历结果:");LevelOrder_BiTree(T);printf("\n");deepth=TreeDeep(T);printf("树的深度为:%d",deepth);printf("\n");printf("树的叶子结点为:");Leafcount(T,num);printf("\\n树的叶子结点个数为:%d",num);return 0;}二、运行结果(截图)三、遇到的问题总结通过死循环的部分可以看出,在判断时是不能进入结点为空的语句中的,于是从树的构建中寻找问题,最终发现这一条语句存在着问题:这里给T赋值为空,也就是给整个结构体地址赋值为空,但是我们的目的是给该结构体中的内容,即左孩子的地址指向的内容赋为空。

北邮数据结构平衡二叉树报告概论

北邮数据结构平衡二叉树报告概论

数据结构实验报告实验名称:平衡二叉树1.实验目的和内容根据平衡二叉树的抽象数据类型的定义,使用二叉链表实现一个平衡二叉树。

二叉树的基本功能:1、平衡二叉树的建立2、平衡二叉树的查找3、平衡二叉树的插入4、平衡二叉树的删除5、平衡二叉树的销毁6、其他:自定义操作编写测试main()函数测试平衡二叉树的正确性。

2. 程序分析2.1 存储结构struct node{int key; //值int height; //这个结点的父节点在这枝最长路径上的结点个数node *left; //左孩子指针node *right; //右孩子指针node(int k){ key = k; left = right = 0; height = 1; } //构造函数};2.2 程序流程2.3 关键算法分析(由于函数过多,在此只挑选部分重要函数)算法1:void AVL_Tree::left_rotate(node *&x)[1] 算法功能:对 R-R型进行调整[2] 算法基本思想:将结点右孩子进行逆时针旋转[3] 算法空间、时间复杂度分析:都为0(1)[4] 代码逻辑node *y = x->right; y为x的右孩子x->right = y->left; 将y的左孩子赋给x的右孩子 y->left = x; x变为y的左孩子fixheight(x); 修正x,y的height值fixheight(y);x = y; 使x的父节点指向y 算法2:void A VL_Tree::right_rotate(node *&x)[1] 算法功能:对L-L型进行调整[2] 算法基本思想:将左孩子进行顺时针旋转[3] 算法空间、时间复杂度分析:都为0(1)[4] 代码逻辑node *y = x->left; //y为x的左孩子 x->left = y->right; y的右孩子赋给x的左孩子y->right = x; x变为y的右孩子fixheight(x); 修正x和y的height值fixheight(y);x = y; 使x的父节点指向y算法3:node*& A VL_Tree::balance(node *&p)[1] 算法功能:对给定结点进行平衡操作[2] 算法基本思想:通过平衡因子判断属于哪种情况,再依照情况进行平衡[3] 算法空间、时间复杂度分析:没有递归和循环,都为O(1)[4] 代码逻辑fixheight(p); //修正P的height值if (bfactor(p) == 2) 平衡因子为2,为L-?型if (bfactor(p->left) < 0) P的左孩子平衡因子<0时,为L-R型,执行left_rotate(p->left); 相关平衡操作,若>0,为L-L型。

数据结构程序的设计报告(平衡二叉树)

数据结构程序的设计报告(平衡二叉树)

数学与计算机科学学院数据结构程序设计报告平衡二叉树学生姓名:学号:班级:指导老师:报告日期:1.题目与要求1). 问题的提出编写已个平衡二叉树,主要是对插入一个元素导致树不平衡的情况进行平衡化处理以及相关的处理。

2)设计的知识点队列的插入,删除,二叉树的建立于销毁,平衡树的平衡化,以及C语言中基础应用于结构等。

3)功能要求(1).通过不断插入的方式创建一棵平衡二叉树,包括输入结点的关键字和相关信息。

(2)按要求输出创建的平衡二叉树结点,包括顺序(中序)输出和按层次输出。

(3)插入新增的结点,若结点不存在则插入平衡二叉树,并进行相关调整。

(4)销毁二叉树。

(5)退出菜单界面如下:2.功能设计算法设计选择创建平衡二叉树后,利用循环不断插入结点,并进行调整,当输入节点为0时停止进入菜单界面。

在平横二叉树排序树BSTree上插入一个新的数据元素e的递归算法可如下描述:(1)若BSTree为空树,则插入一个数据元素为e的新结点作为BSTree的根结点,树的深度增1;(2)若e的关键字和BSTree的根节点的关键字相等,则不进行插入;(3)若e的关键字小于BSTree的根结点的关键字,而且在其左子树中不存在和e形同的关键字的结点,则将e插入在其左子树上,并且当插入之后的左子树的深度加1时,分别就下列不同情况处理之:a.BSTree的跟结点的平衡因子为-1(右子树的深度大于左子树的深度):则将跟结点的平衡因子更改为0,BBST的深度不变;b.BBST的根结点的平衡因子为0(左,右子树的深度相等):则将根结点的平衡因子更改为1,BBST的深度增1;c.BBST的根结点的平衡因子为1(左子树的深度大于右子树的深度):若BBST的左子树根结点的平衡因子为1,则需进行向左旋平衡处理,并且在右旋之后,将根节点和其右子树根节点的平衡因子更改为0,树的深度不变;若BBST的左子树根结点的平衡因子为-1,则需进行向左,向右的双向旋转平衡处理,并且在旋转处理之后,修改根结点和其左右子树的平衡因子,数的深度不变;(4)若e的关键字大于BBST的根结点的关键字,而且在BBST的右子树中不存在和e有相同的关键字的的节点,则将e插入在BBST的右子树上,并且当插入之后的右子树深度增加(+1)时,分别就不同情况处理之。

数据结构程序报告

数据结构程序报告

数据结构程序报告数据结构,是计算机科学中一门研究各种数据的存储方式、组织方式和管理方式的学科,是计算机科学的基础课程之一、平衡二叉树,是数据结构中的一种重要的树结构,其能够在插入和删除的过程中自动保持其左右子树高度的平衡。

本文将对平衡二叉树的操作进行详细介绍。

首先,平衡二叉树的特点是每个节点的左右子树的高度差不超过1、这样一来,平衡二叉树的查找、插入和删除的时间复杂度均能保持在O(logn)的级别,使得其在大规模数据处理中具有较高的效率。

为了保持平衡,我们需要对插入和删除操作进行一系列的旋转操作。

平衡二叉树的插入操作分为两个步骤:首先进行二叉查找树的插入操作,然后对每个经过的节点检查其平衡因子,如果平衡因子超过了1或-1,则需要进行相应的旋转操作。

常用的旋转操作有左旋和右旋。

左旋是指以一些节点为支点,使其右子树成为新的支点,原支点成为新支点的左子树。

右旋与左旋的操作类似,只是方向相反。

通过旋转操作,可以让插入后的平衡二叉树保持平衡。

平衡二叉树的删除操作分为三个步骤:首先进行二叉查找树的删除操作,然后对每个经过的节点检查其平衡因子,如果平衡因子超过了1或-1,则需要进行相应的旋转操作;最后,检查删除节点的父节点是否平衡,如果不平衡,则需要进行旋转操作。

删除操作涉及到对树的旋转和重新平衡的过程,操作较为复杂。

平衡二叉树的查询操作与普通的二叉查找树类似,通过比较节点的值大小来确定当前节点的位置,进而进行查找。

由于平衡二叉树的平衡性,查询的时间复杂度能够保持在O(logn)的级别。

总结来说,平衡二叉树是一种能够在插入和删除过程中自动保持平衡的树结构。

通过旋转操作和调整平衡因子,可以在一定程度上减少二叉树的高度,提高插入、删除和查询的效率。

但是,由于平衡二叉树的调整过程较为繁琐,实际应用中一般采用平衡二叉树的变种,如AVL树、红黑树等。

在实际应用中,平衡二叉树的操作是数据结构领域的一个关键问题,对于构建高效的数据存储和处理系统具有重要意义。

实验报告-平衡二叉树

实验报告-平衡二叉树

实习报告一、需求分析1、问题描述利用平衡二‎叉树实现一‎个动态查找‎表。

(1)实现动态查‎找表的三种‎基本功能:查找、插入和删除‎。

(2)初始时,平衡二叉树‎为空树,操作界面给‎出查找、插入和删除‎三种操作供‎选择。

每种操作均‎要提示输入‎关键字。

在查找时,如果查找的‎关键字不存‎在,则把其插入‎到平衡二叉‎树中。

每次插入或‎删除一个结‎点后,应更新平衡‎二叉树的显‎示。

(3)每次操作的‎关键字都要‎从文件中读‎取,并且关键字‎的集合限定‎为短整型数‎字{1,2,3······},关键字出现‎的顺序没有‎限制,允许出现重‎复的关键字‎,并对其进行‎相应的提示‎。

(4)平衡二叉树‎的显示采用‎图形界面画‎出图形。

2、系统功能打开数据文‎件,用文件中的‎关键字来演‎示平衡二叉‎树操作的过‎程。

3、程序中执行‎的命令包括‎:(1)(L)oad from data file //在平衡的二‎叉树中插入‎关键字;(2)(A)ppend‎new recor‎d//在平衡的二‎叉树中查找‎关键字;(3)(U)pate speci‎a l recor‎d//显示调整过‎的平衡二叉‎树;(4)(D)elete‎speci‎a l recor‎d//删除平衡二‎叉树中的关‎键字;(5)(Q)uit //结束。

4、测试数据:平衡二叉树‎为:图 1 插入关键字‎10之前的‎平衡二叉树‎插入关键字‎:10;调整后:图 2 插入关键字‎10之后的‎平衡二叉树‎删除关键字‎:14;调整后:图 3 删除关键字‎14后的平‎衡二叉树查找关键字‎:11;输出:The data is here!图 3 查找关键字‎11后的平‎衡二叉树二、概要设计本次实验目‎的是为了实‎现动态查找‎表的三种基‎本功能:查找、插入和删除‎。

动态查找表‎可有不同的‎表示方法,在此次实验‎中主要是以‎平衡二叉树‎的结构来表‎示实现的,所以需要两‎个抽象数据‎类型:动态查找表‎和二叉树。

数据结构实验报告 二叉树

数据结构实验报告 二叉树

数据结构实验报告二叉树数据结构实验报告:二叉树引言:数据结构是计算机科学中的重要基础,它为我们提供了存储和组织数据的方式。

二叉树作为一种常见的数据结构,广泛应用于各个领域。

本次实验旨在通过实践,深入理解二叉树的概念、性质和操作。

一、二叉树的定义与性质1.1 定义二叉树是一种特殊的树结构,每个节点最多有两个子节点,分别称为左子节点和右子节点。

二叉树可以为空树,也可以是由根节点和左右子树组成的非空树。

1.2 基本性质(1)每个节点最多有两个子节点;(2)左子树和右子树是有顺序的,不能颠倒;(3)二叉树的子树仍然是二叉树。

二、二叉树的遍历2.1 前序遍历前序遍历是指首先访问根节点,然后按照先左后右的顺序遍历左右子树。

在实际应用中,前序遍历常用于复制一颗二叉树或创建二叉树的副本。

2.2 中序遍历中序遍历是指按照先左后根再右的顺序遍历二叉树。

中序遍历的结果是一个有序序列,因此在二叉搜索树中特别有用。

2.3 后序遍历后序遍历是指按照先左后右再根的顺序遍历二叉树。

后序遍历常用于计算二叉树的表达式或释放二叉树的内存。

三、二叉树的实现与应用3.1 二叉树的存储结构二叉树的存储可以使用链式存储或顺序存储。

链式存储使用节点指针连接各个节点,而顺序存储则使用数组来表示二叉树。

3.2 二叉树的应用(1)二叉搜索树:二叉搜索树是一种特殊的二叉树,它的左子树上的节点都小于根节点,右子树上的节点都大于根节点。

二叉搜索树常用于实现查找、插入和删除等操作。

(2)堆:堆是一种特殊的二叉树,它满足堆序性质。

堆常用于实现优先队列,如操作系统中的进程调度。

(3)哈夫曼树:哈夫曼树是一种带权路径最短的二叉树,常用于数据压缩和编码。

四、实验结果与总结通过本次实验,我成功实现了二叉树的基本操作,包括创建二叉树、遍历二叉树和查找节点等。

在实践中,我进一步理解了二叉树的定义、性质和应用。

二叉树作为一种重要的数据结构,在计算机科学中有着广泛的应用,对于提高算法效率和解决实际问题具有重要意义。

平衡二叉树操作演示.doc

平衡二叉树操作演示.doc

平衡二叉树操作演示.数据结构实习报告题目:平衡二叉树的操作演示班级:信息管理与信息系统11-平衡二叉树的操作演示班级:信息管理与信息系统11:崔佳学号:201101050903完成日期:2013.06.25一、需求分析1. 初始,平衡二叉树为空树,操作界面给出两棵平衡二叉树的显示、查找、插入、删除、销毁、合并两棵树,几种选择。

其中查找、插入和删除操作均要提示用户输入关键字。

每次插入或删除一个节点后都会更新平衡二叉树的显示。

2. 平衡二叉树的显示采用凹入表形式。

3.每次操作完毕后都会给出相应的操作结果,并进入下一次操作,知道用户选择退出二、概要设计1.平衡二叉树的抽象数据类型定义:ADT BalancedBinaryTree{ 数据对象D:D是具有相同特性的数据元素的集合。

各个数据元素均含有类型相同,可唯一标志的数据元素的关键字。

数据关系R:数据元素同属一个集合。

基本操作P:InitA VL(BSTree T) 操作结果:构造一个空的平衡二叉树T DestroyA VL(BSTree T) 初始条件:平衡二叉树T存在操作结果:销毁平衡二叉树T SearchA VL(BSTree T,int key) 初始条件:平衡二叉树T存在,key为和关键字相同类型的给定值操作结果:若T中存在关键字和key相等的数据元素,则返回指向该元素的指针,否则为空InsertA VL(BSTree T,int key,Status taller) 初始条件:平衡二叉树T存在,key和关键字的类型相同操作结果:若T中存在关键字等于key的数据元素则返回,若不存在则插入一个关键字为key的元素DeleteA VL(BSTree T,int key,Status lower) 初始条件:平衡二叉树T存在,key和关键字的类型相同操作结果:若T中存在关键字和key相同的数据元素则删除它}ADT BalancedBinaryTree2.本程序包含二个模块1)主程序模块:void main(){ 接收命令;While(“命令”!=“退出”){ 处理命令;清屏并得新打印提示信息;接收下一条命令;}}2)平衡二叉树基本操作实现平衡二叉树的抽象数据类型的各函数原型。

[精品]【数据结构】二叉树实验报告

[精品]【数据结构】二叉树实验报告

[精品]【数据结构】二叉树实验报告二叉树实验报告一、实验目的:1.掌握二叉树的基本操作;2.理解二叉树的性质;3.熟悉二叉树的广度优先遍历和深度优先遍历算法。

二、实验原理:1.二叉树是一种树形结构,由n(n>=0)个节点组成;2.每个节点最多有两个子节点,称为左子节点和右子节点;3.二叉树的遍历分为四种方式:前序遍历、中序遍历、后序遍历和层次遍历。

三、实验环境:1.编程语言:C++;2.编译器:Dev-C++。

四、实验内容:1.定义二叉树节点结构体:struct BinaryTreeNode{int data; // 节点数据BinaryTreeNode *leftChild; // 左子节点指针BinaryTreeNode *rightChild; // 右子节点指针};2.初始化二叉树:queue<BinaryTreeNode *> q; // 使用队列存储节点q.push(root);int i = 1; // 创建子节点while (!q.empty() && i < length){BinaryTreeNode *node = q.front();q.pop();if (data[i] != -1) // 创建左子节点 {BinaryTreeNode *leftChild = new BinaryTreeNode;leftChild->data = data[i];leftChild->leftChild = nullptr;leftChild->rightChild = nullptr;node->leftChild = leftChild;q.push(leftChild);}i++;if (data[i] != -1) // 创建右子节点 {BinaryTreeNode *rightChild = new BinaryTreeNode;rightChild->data = data[i];rightChild->leftChild = nullptr;rightChild->rightChild = nullptr;node->rightChild = rightChild;q.push(rightChild);}i++;}return root;}3.前序遍历二叉树:五、实验结果:输入:int data[] = {1, 2, 3, 4, -1, -1, 5, 6, -1, -1, 7, 8};输出:前序遍历结果:1 2 4 5 3 6 7 8中序遍历结果:4 2 5 1 6 3 7 8后序遍历结果:4 5 2 6 8 7 3 1层次遍历结果:1 2 3 4 5 6 7 8通过本次实验,我深入理解了二叉树的性质和遍历方式,并掌握了二叉树的基本操作。

数据结构二叉树的实验报告

数据结构二叉树的实验报告

数据结构二叉树的实验报告数据结构二叉树的实验报告一、引言数据结构是计算机科学中非常重要的一个领域,它研究如何组织和存储数据以便高效地访问和操作。

二叉树是数据结构中常见且重要的一种,它具有良好的灵活性和高效性,被广泛应用于各种领域。

本实验旨在通过实际操作和观察,深入了解二叉树的特性和应用。

二、实验目的1. 理解二叉树的基本概念和特性;2. 掌握二叉树的创建、遍历和查找等基本操作;3. 通过实验验证二叉树的性能和效果。

三、实验过程1. 二叉树的创建在实验中,我们首先需要创建一个二叉树。

通过输入一系列数据,我们可以按照特定的规则构建一棵二叉树。

例如,可以按照从小到大或从大到小的顺序将数据插入到二叉树中,以保证树的有序性。

2. 二叉树的遍历二叉树的遍历是指按照一定的次序访问二叉树中的所有节点。

常见的遍历方式有前序遍历、中序遍历和后序遍历。

前序遍历是先访问根节点,然后再依次遍历左子树和右子树;中序遍历是先遍历左子树,然后访问根节点,最后再遍历右子树;后序遍历是先遍历左子树,然后遍历右子树,最后访问根节点。

3. 二叉树的查找二叉树的查找是指在二叉树中寻找指定的节点。

常见的查找方式有深度优先搜索和广度优先搜索。

深度优先搜索是从根节点开始,沿着左子树一直向下搜索,直到找到目标节点或者到达叶子节点;广度优先搜索是从根节点开始,逐层遍历二叉树,直到找到目标节点或者遍历完所有节点。

四、实验结果通过实验,我们可以观察到二叉树的特性和性能。

在创建二叉树时,如果按照有序的方式插入数据,可以得到一棵平衡二叉树,其查找效率较高。

而如果按照无序的方式插入数据,可能得到一棵不平衡的二叉树,其查找效率较低。

在遍历二叉树时,不同的遍历方式会得到不同的结果。

前序遍历可以用于复制一棵二叉树,中序遍历可以用于对二叉树进行排序,后序遍历可以用于释放二叉树的内存。

在查找二叉树时,深度优先搜索和广度优先搜索各有优劣。

深度优先搜索在空间复杂度上较低,但可能会陷入死循环;广度优先搜索在时间复杂度上较低,但需要较大的空间开销。

数据结构实验报告—二叉树

数据结构实验报告—二叉树

数据结构实验报告—二叉树数据结构实验报告—二叉树引言二叉树是一种常用的数据结构,它由节点和边构成,每个节点最多有两个子节点。

在本次实验中,我们将对二叉树的基本结构和基本操作进行实现和测试,并深入了解它的特性和应用。

实验目的1. 掌握二叉树的基本概念和特性2. 熟练掌握二叉树的基本操作,包括创建、遍历和查找等3. 了解二叉树在实际应用中的使用场景实验内容1. 二叉树的定义和存储结构:我们将首先学习二叉树的定义,并实现二叉树的存储结构,包括节点的定义和节点指针的表示方法。

2. 二叉树的创建和初始化:我们将实现二叉树的创建和初始化操作,以便后续操作和测试使用。

3. 二叉树的遍历:我们将实现二叉树的前序、中序和后序遍历算法,并测试其正确性和效率。

4. 二叉树的查找:我们将实现二叉树的查找操作,包括查找节点和查找最大值、最小值等。

5. 二叉树的应用:我们将探讨二叉树在实际应用中的使用场景,如哈夫曼编码、二叉搜索树等。

二叉树的定义和存储结构二叉树是一种特殊的树形结构,它的每个节点最多有两个子节点。

节点被表示为一个由数据和指向其左右子节点的指针组成的结构。

二叉树可以分为三类:满二叉树、完全二叉树和非完全二叉树。

二叉树可以用链式存储结构或顺序存储结构表示。

- 链式存储结构:采用节点定义和指针表示法,通过将节点起来形成一个树状结构来表示二叉树。

- 顺序存储结构:采用数组存储节点信息,通过计算节点在数组中的位置来进行访问和操作。

二叉树的创建和初始化二叉树的创建和初始化是二叉树操作中的基础部分。

我们可以通过手动输入或读取外部文件中的数据来创建二叉树。

对于链式存储结构,我们需要自定义节点和指针,并通过节点的方式来构建二叉树。

对于顺序存储结构,我们需要定义数组和索引,通过索引计算来定位节点的位置。

一般来说,初始化一个二叉树可以使用以下步骤:1. 创建树根节点,并赋初值。

2. 创建子节点,并到父节点。

3. 重复步骤2,直到创建完整个二叉树。

数据结构二叉树实验报告

数据结构二叉树实验报告

数据结构二叉树实验报告二叉树是一种常用的数据结构,它在计算机科学中有着广泛的应用。

本文将介绍二叉树的定义、基本操作以及一些常见的应用场景。

一、二叉树的定义和基本操作二叉树是一种特殊的树形结构,它的每个节点最多有两个子节点。

一个节点的左子节点称为左子树,右子节点称为右子树。

二叉树的示意图如下:```A/ \B C/ \D E```在二叉树中,每个节点可以有零个、一个或两个子节点。

如果一个节点没有子节点,我们称之为叶子节点。

在上面的示例中,节点 D 和 E 是叶子节点。

二叉树的基本操作包括插入节点、删除节点、查找节点和遍历节点。

插入节点操作可以将一个新节点插入到二叉树中的合适位置。

删除节点操作可以将一个指定的节点从二叉树中删除。

查找节点操作可以在二叉树中查找指定的节点。

遍历节点操作可以按照一定的顺序遍历二叉树中的所有节点。

二、二叉树的应用场景二叉树在计算机科学中有着广泛的应用。

下面将介绍一些常见的应用场景。

1. 二叉搜索树二叉搜索树是一种特殊的二叉树,它的每个节点的值都大于其左子树中的节点的值,小于其右子树中的节点的值。

二叉搜索树可以用来实现快速的查找、插入和删除操作。

它在数据库索引、字典等场景中有着重要的应用。

2. 堆堆是一种特殊的二叉树,它的每个节点的值都大于或小于其子节点的值。

堆可以用来实现优先队列,它在任务调度、操作系统中的内存管理等场景中有着重要的应用。

3. 表达式树表达式树是一种用来表示数学表达式的二叉树。

在表达式树中,每个节点可以是操作符或操作数。

表达式树可以用来实现数学表达式的计算,它在编译器、计算器等场景中有着重要的应用。

4. 平衡二叉树平衡二叉树是一种特殊的二叉树,它的左子树和右子树的高度差不超过1。

平衡二叉树可以用来实现高效的查找、插入和删除操作。

它在数据库索引、自平衡搜索树等场景中有着重要的应用。

三、总结二叉树是一种常用的数据结构,它在计算机科学中有着广泛的应用。

本文介绍了二叉树的定义、基本操作以及一些常见的应用场景。

数据结构实验三——二叉树基本操作及运算实验报告

数据结构实验三——二叉树基本操作及运算实验报告

《数据结构与数据库》实验报告实验题目二叉树的基本操作及运算一、需要分析问题描述:实现二叉树(包括二叉排序树)的建立,并实现先序、中序、后序和按层次遍历,计算叶子结点数、树的深度、树的宽度,求树的非空子孙结点个数、度为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. 引言二叉树是一种常见的数据结构,由节点(Node)和链接(Link)构成。

每个节点最多有两个子节点,分别称为左子节点和右子节点。

二叉树在计算机科学中被广泛应用,例如在搜索算法中,二叉树可以用来快速查找和插入数据。

本实验旨在通过编写二叉树的基本操作来深入理解二叉树的特性和实现方式。

2. 实验内容2.1 二叉树的定义二叉树可以用以下方式定义:class TreeNode:def__init__(self, val):self.val = valself.left =Noneself.right =None每个节点包含一个值和两个指针,分别指向左子节点和右子节点。

根据需求,可以为节点添加其他属性。

2.2 二叉树的基本操作本实验主要涉及以下二叉树的基本操作:•创建二叉树:根据给定的节点值构建二叉树。

•遍历二叉树:将二叉树的节点按照特定顺序访问。

•查找节点:在二叉树中查找特定值的节点。

•插入节点:向二叉树中插入新节点。

•删除节点:从二叉树中删除特定值的节点。

以上操作将在下面章节详细讨论。

3. 实验步骤3.1 创建二叉树二叉树可以通过递归的方式构建。

以创建一个简单的二叉树为例:def create_binary_tree():root = TreeNode(1)root.left = TreeNode(2)root.right = TreeNode(3)root.left.left = TreeNode(4)root.left.right = TreeNode(5)return root以上代码创建了一个二叉树,根节点的值为1,左子节点值为2,右子节点值为3,左子节点的左子节点值为4,左子节点的右子节点值为5。

3.2 遍历二叉树二叉树的遍历方式有多种,包括前序遍历、中序遍历和后序遍历。

以下是三种遍历方式的代码实现:•前序遍历:def preorder_traversal(root):if root:print(root.val)preorder_traversal(root.left)preorder_traversal(root.right)•中序遍历:def inorder_traversal(root):if root:inorder_traversal(root.left)print(root.val)inorder_traversal(root.right)•后序遍历:def postorder_traversal(root):if root:postorder_traversal(root.left)postorder_traversal(root.right)print(root.val)3.3 查找节点在二叉树中查找特定值的节点可以使用递归的方式实现。

数据结构实验报告-树(二叉树)

数据结构实验报告-树(二叉树)

实验5:树(二叉树)(采用二叉链表存储)一、实验项目名称二叉树及其应用二、实验目的熟悉二叉树的存储结构的特性以及二叉树的基本操作。

三、实验基本原理之前我们都是学习的线性结构,这次我们就开始学习非线性结构——树。

线性结构中结点间具有唯一前驱、唯一后继关系,而非线性结构中结点的前驱、后继的关系并不具有唯一性。

在树结构中,节点间关系是前驱唯一而后继不唯一,即结点之间是一对多的关系。

直观地看,树结构是具有分支关系的结构(其分叉、分层的特征类似于自然界中的树)。

四、主要仪器设备及耗材Window 11、Dev-C++5.11五、实验步骤1.导入库和预定义2.创建二叉树3.前序遍历4.中序遍历5.后序遍历6.总结点数7.叶子节点数8.树的深度9.树根到叶子的最长路径10.交换所有节点的左右子女11.顺序存储12.显示顺序存储13.测试函数和主函数对二叉树的每一个操作写测试函数,然后在主函数用while+switch-case的方式实现一个带菜单的简易测试程序,代码见“实验完整代码”。

实验完整代码:#include <bits/stdc++.h>using namespace std;#define MAX_TREE_SIZE 100typedef char ElemType;ElemType SqBiTree[MAX_TREE_SIZE];struct BiTNode{ElemType data;BiTNode *l,*r;}*T;void createBiTree(BiTNode *&T){ElemType e;e = getchar();if(e == '\n')return;else if(e == ' ')T = NULL;else{if(!(T = (BiTNode *)malloc(sizeof (BiTNode)))){cout << "内存分配错误!" << endl;exit(0);}T->data = e;createBiTree(T->l);createBiTree(T->r);}}void createBiTree2(BiTNode *T,int u) {if(T){SqBiTree[u] = T->data;createBiTree2(T->l,2 * u + 1);createBiTree2(T->r,2 * u + 2); }}void outputBiTree2(int n){int cnt = 0;for(int i = 0;cnt <= n;i++){cout << SqBiTree[i];if(SqBiTree[i] != ' ')cnt ++;}cout << endl;}void preOrderTraverse(BiTNode *T) {if(T){cout << T->data;preOrderTraverse(T->l);preOrderTraverse(T->r);}}void inOrderTraverse(BiTNode *T) {if(T){inOrderTraverse(T->l);cout << T->data;inOrderTraverse(T->r);}}void beOrderTraverse(BiTNode *T){if(T){beOrderTraverse(T->l);beOrderTraverse(T->r);cout << T->data;}}int sumOfVer(BiTNode *T){if(!T)return 0;return sumOfVer(T->l) + sumOfVer(T->r) + 1;}int sumOfLeaf(BiTNode *T){if(!T)return 0;if(T->l == NULL && T->r == NULL)return 1;return sumOfLeaf(T->l) + sumOfLeaf(T->r);}int depth(BiTNode *T){if(!T)return 0;return max(depth(T->l),depth(T->r)) + 1;}bool LongestPath(int dist,int dist2,vector<ElemType> &ne,BiTNode *T) {if(!T)return false;if(dist2 == dist)return true;if(LongestPath(dist,dist2 + 1,ne,T->l)){ne.push_back(T->l->data);return true;}else if(LongestPath(dist,dist2 + 1,ne,T->r)){ne.push_back(T->r->data);return true;}return false;}void swapVer(BiTNode *&T){if(T){swapVer(T->l);swapVer(T->r);BiTNode *tmp = T->l;T->l = T->r;T->r = tmp;}}//以下是测试程序void test1(){getchar();cout << "请以先序次序输入二叉树结点的值,空结点用空格表示:" << endl; createBiTree(T);cout << "二叉树创建成功!" << endl;}void test2(){cout << "二叉树的前序遍历为:" << endl;preOrderTraverse(T);cout << endl;}void test3(){cout << "二叉树的中序遍历为:" << endl;inOrderTraverse(T);cout << endl;}void test4(){cout << "二叉树的后序遍历为:" << endl;beOrderTraverse(T);cout << endl;}void test5(){cout << "二叉树的总结点数为:" << sumOfVer(T) << endl;}void test6(){cout << "二叉树的叶子结点数为:" << sumOfLeaf(T) << endl; }void test7(){cout << "二叉树的深度为:" << depth(T) << endl;}void test8(){int dist = depth(T);vector<ElemType> ne;cout << "树根到叶子的最长路径:" << endl;LongestPath(dist,1,ne,T);ne.push_back(T->data);reverse(ne.begin(),ne.end());cout << ne[0];for(int i = 1;i < ne.size();i++)cout << "->" << ne[i];cout << endl;}void test9(){swapVer(T);cout << "操作成功!" << endl;}void test10(){memset(SqBiTree,' ',sizeof SqBiTree);createBiTree2(T,0);cout << "操作成功!" << endl;}void test11(){int n = sumOfVer(T);outputBiTree2(n);}int main(){int op = 0;while(op != 12){cout << "-----------------menu--------------------" << endl;cout << "--------------1:创建二叉树--------------" << endl;cout << "--------------2:前序遍历----------------" << endl;cout << "--------------3:中序遍历----------------" << endl;cout << "--------------4:后序遍历----------------" << endl;cout << "--------------5:总结点数----------------" << endl;cout << "--------------6:叶子节点数--------------" << endl;cout << "--------------7:树的深度----------------" << endl;cout << "--------------8:树根到叶子的最长路径----" << endl;cout << "--------------9:交换所有节点左右子女----" << endl;cout << "--------------10:顺序存储---------------" << endl;cout << "--------------11:显示顺序存储-----------" << endl;cout << "--------------12:退出测试程序-----------" << endl;cout << "请输入指令编号:" << endl;if(!(cin >> op)){cin.clear();cin.ignore(INT_MAX,'\n');cout << "请输入整数!" << endl;continue;}switch(op){case 1:test1();break;case 2:test2();break;case 3:test3();break;case 4:test4();break;case 5:test5();break;case 6:test6();break;case 7:test7();break;case 8:test8();break;case 9:test9();break;case 10:test10();break;case 11:test11();break;case 12:cout << "测试结束!" << endl;break;default:cout << "请输入正确的指令编号!" << endl;}}return 0;}六、实验数据及处理结果测试用例:1.创建二叉树(二叉链表形式)2.前序遍历3.中序遍历4.后序遍历5.总结点数6.叶子结点数7.树的深度8.树根到叶子的最长路径9.交换所有左右子女10.顺序存储七、思考讨论题或体会或对改进实验的建议通过这次实验,我掌握了二叉树的顺序存储和链式存储,体会了二叉树的存储结构的特性,掌握了二叉树的树上相关操作。

广工数据结构实验报告平衡二叉树

广工数据结构实验报告平衡二叉树

数据结构实验报告题目:平衡二叉树学院专业年级班别学号学生姓名指导教师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("平衡二叉树创建结束。

数据结构平衡二叉树的操作演示

数据结构平衡二叉树的操作演示

数据结构平衡二叉树的操作演示平衡二叉树(AVL树)是一种自平衡的二叉树,可以在O(log n)的时间内完成插入、删除和操作。

AVL树的平衡性是通过对树节点进行左旋和右旋操作来实现的。

下面将详细介绍AVL树的操作演示。

AVL树的定义和二叉树相似,每个节点包含一个键值和指向左右子树的指针。

任意节点的左子树和右子树的高度最多相差1,这个特性使得AVL树始终保持平衡。

1.插入操作插入操作是AVL树中最复杂的操作之一,因为插入后可能会破坏树的平衡性。

下面通过一个示例来演示AVL树的插入操作。

假设我们要向一棵空树插入节点5,插入过程如下:1.创建一个新节点,值为52.将新节点插入根节点。

3.检查树的平衡性。

根据AVL树的定义,左子树和右子树的高度差最多为1、在这个例子中,树是平衡的。

4.更新每个节点的高度值。

如果我们插入节点6,插入过程如下:1.创建一个新节点,值为62.将新节点插入到节点5的右子树。

3.检查树的平衡性。

在这个例子中,树不再是平衡的,因为节点5的左子树和右子树的高度差为24.执行旋转操作来恢复树的平衡性。

在这个例子中,我们需要对节点5进行左旋操作。

5.更新每个节点的高度值。

2.删除操作删除操作是AVL树中另一个可能破坏树的平衡性的操作。

下面通过一个示例来演示AVL树的删除操作。

假设我们要删除节点5,删除过程如下:1.在树中找到要删除的节点,即节点52.如果要删除的节点是叶子节点或只有一个子节点,直接删除。

在这个例子中,节点5是一个叶子节点,可以直接删除。

3.如果要删除的节点有两个子节点,找到其后继节点(即右子树中的最小节点)或前驱节点(即左子树中的最大节点)来取代它。

在这个例子中,我们找到节点6来取代节点54.如果取代节点是叶子节点或只有一个子节点,直接用它取代要删除的节点。

在这个例子中,我们用节点6取代了节点55.检查树的平衡性。

在这个例子中,树是平衡的。

6.更新每个节点的高度值。

3.左旋操作左旋操作用于恢复树的平衡性。

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

数据结构程序报告(平衡二叉树的操作)计算机科学学院数据结构课程设计报告平衡二叉树操作学生姓名:学号:班级:指导老师:报告日期: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);//插入结点ebool SearchBST(BSTree &T,int key); //查找元素key是否在树T中void LeftBalance_div(BSTree &p,int &shorter); void RightBalance_div(BSTree &p,int &shorter);void Delete(BSTree q,BSTree &r,int &shorter); //删除结点int DeleteA VL(BSTree &p,int x,int &shorter);void PrintBST(BSTree T,int m);2.主程序的流程3.各模块之间的层次调用3.详细设计1.以平衡二叉树的插入和平衡化为例:bool InsertA VL(BSTree &T,int e,bool &taller) {//若存在平衡的二叉排序树T中不存在和e有相//的新结点,并返回1,否者返回0。

若因插入而//布尔变量taller反映T长高与否。

if(!T)//插入新结点,树“长高”,置taller为{T = (BSTree)malloc(sizeof(BSTNode));T->data = e;T->lchild = T->rchild =NULL;T->bf = EH; taller = true;}else{if(EQ(e,T->data)) //{ taller = false;printf("已存在相同关键if(LT(e,T->data)) //{if(!InsertA VL(T->lchild,e,taller))if(taller) //switch(T->bf){case LH:LeftBalance(T); taller case EH:T->bf = LH; taller =case RH:T->bf = EH; taller =}//switch(T->bf) }//ifelse{if(!InsertA VL(T->rchild,e,taller)) if(taller) //switch(T->bf){case LH:T->bf = EH; taller = case EH:T->bf = RH; taller =case RH:RightBalance(T);}//switch(T->bf)}//else}//elsereturn 1;}//InsertA VL2.说明:执行完输入函数后,会在键盘缓冲区中保存回车键,后面再对字符型量赋值时,会将缓冲区当成数据存入变量中,所以要在某些输入语句后面加getchar 函数。

4.调试分析1.遇到的问题:(1)对平衡二叉树的删除的算法设计程序存在很大问题。

删除节点后需要对新的排序树平衡化,改变节点的信息,使之形成一棵新的平衡二叉树。

(2)主函数中的实参和子函数中的实参相等,造成调用该子函数时,虽然没有错误,但其功能不能正确的实现。

改变该变量后程序成功实现各种功能。

(3)一些逻辑逻辑运算符书写不正确,造成实现的功能不正确或程序死循环。

……2.收获:(1)对平衡二叉树的构造、插入和删除的算法思想有了更清楚的认识,能够对平衡二叉树进行创建、调平、插入、删除等操作,实现动态的输入数据,实时的输出该树结构.(2)对多个程序的调用5.用户使用说明1.了解程序清单上给出的功能,并根据提示依次进行操作。

2.创建二叉树,输入的数据元素为整数,当输入-123时,停止创建。

并显示平衡二叉树的中序凹入树形图。

3.查找(输入你要查找的元素)。

4.插入(输入要插入的数据元素,并输出)5.删除(删除指定的元素,并输出)6.结束说明:其中每一个功能实现后都会提示是否继续:选择y继续,否则,终止。

6.测试结果1.创建平衡二叉树:(中序凹入输出)2.查找查找成功或失败时:3.插入4.删除,结束7.附录源代码:#include<stdio.h>#include<stdlib.h>#define LH +1#define EH 0#define RH -1#define NULL 0typedef struct BSTNode {int data;int bf;struct BSTNode *lchild,*rchild;}BSTNode,*BSTree;void CreatBST(BSTree &T);void R_Rotate (BSTree &p);void L_Rotate(BSTree &p);void LeftBalance(BSTree &T);void RightBalance(BSTree &T);bool InsertA VL(BSTree &T,int e,bool &taller); bool SearchBST(BSTree &T,int key);void LeftBalance_div(BSTree &p,int &shorter);void RightBalance_div(BSTree &p,int &shorter);void Delete(BSTree q,BSTree &r,int &shorter);int DeleteA VL(BSTree &p,int x,int &shorter); void PrintBST(BSTree T,int depth);void main(){BSTree T;int sear,cmd,depth;char ch;int shorter=0;bool taller=false;T=(BSTree)malloc(sizeof(BSTNode));T=NULL;printf("****************平衡二叉树的操作菜单****************\n");printf(" 1--创建\n"); printf(" 2--查找\n");printf(" 3--插入\n");printf(" 4--删除\n");printf(" 5--退出\n"); printf("******************************** ********************\n");do{printf("\n请选择操作的编号:");scanf("%d",&cmd);getchar();switch(cmd){case 1:CreatBST(T);break;case 2:printf("请输入您要查找的关键字:");scanf("%d",&sear);getchar();if(SearchBST(T,sear)) printf("关键字%d 存在,查找成功!\n",sear);else printf("查找失败!\n");break;case 3:printf("请输入您要插入的关键字:");scanf("%d",&sear);getchar;InsertA VL(T,sear,taller);depth=0; PrintBST(T,depth);break;case 4:depth=0;printf("请输入你要删除的关键字: "); scanf("%d",&sear); getchar(); DeleteA VL(T,sear,shorter); PrintBST(T,depth);break;case 5:printf("结束!\n");break;default:printf("输入错误!\n");}if(cmd==5)break;printf("\n继续吗? y/n: ");scanf("%s",&ch);getchar();printf("\n");}while(ch=='y');printf("\n");}void CreatBST(BSTree &T){int depth;int e;bool taller=false;T = NULL;printf("\n请输入关键字(以-123结束建立平衡二叉树):");scanf("%d",&e);getchar();while(e != -123){InsertA VL(T,e,taller);printf("\n请输入关键字(以-123结束建立平衡二叉树):");scanf("%d",&e);getchar();taller=false;}depth=0;printf("\n****************************** **********************\n");printf(" 您创建的二叉树为\n");if(T)PrintBST(T,depth);elseprintf("这是一棵空树!\n");}void R_Rotate (BSTree &p) //对以*p为根的二叉排序树作右旋处理{BSTree lc;lc=p->lchild;p->lchild=lc->rchild;lc->rchild=p;p=lc;}void L_Rotate(BSTree &p) //对以*p为根的二叉排序树作左旋处理{BSTree rc;rc=p->rchild;p->rchild=rc->lchild;rc->lchild=p;p=rc;}void LeftBalance(BSTree &T) //对以指针T所指结点为根的二叉树作左平衡旋转处理{BSTree lc,rd;lc=T->lchild;switch(lc->bf){case LH:T->bf=lc->bf=EH;R_Rotate(T);break;case RH:rd=lc->rchild;switch(rd->bf){case LH:T->bf=RH;lc->bf=EH;break;case EH:T->bf=lc->bf=EH;break;case RH:T->bf=EH;lc->bf=LH;break;}rd->bf=EH;L_Rotate(T->lchild);R_Rotate(T);}}void RightBalance(BSTree &T) //对以指针T所指结点为根的二叉树作右平衡旋转处理{BSTree rc,ld;rc=T->rchild;switch(rc->bf){case RH:T->bf=rc->bf=EH;L_Rotate(T);break;case LH:ld=rc->lchild;switch(ld->bf){case RH:T->bf=LH;rc->bf=EH;break;case EH:T->bf=rc->bf=EH;break;case LH:T->bf=EH;rc->bf=RH;break;}ld->bf=EH;R_Rotate(T->rchild);L_Rotate(T);}}bool InsertA VL(BSTree &T,int e,bool &taller) //插入结点e{if(!T){T=(BSTree)malloc(sizeof(BSTNode));T->data=e;T->lchild=T->rchild=NULL;T->bf=EH;taller=true;}else{if(e==T->data){taller=false;printf("已存在相同关键字的结点!\n");return 0;}if(e<T->data){if(!InsertA VL(T->lchild,e,taller))return 0;if(taller)switch(T->bf){case LH:LeftBalance(T);taller=false;break;case EH:T->bf=LH;taller=true;break;case RH:T->bf=EH;taller=false;break;}}else{if(!InsertA VL(T->rchild,e,taller))return 0;if(taller)switch(T->bf){case LH:T->bf=EH;taller=false;break;case EH:T->bf=RH;taller=true;break;case RH:RightBalance(T);taller=false;break;}}}}bool SearchBST(BSTree &T,int key) //查找元素key是否在树T中{if(!T)return false;else if(key==T->data)return true;else if(key<T->data)return SearchBST(T->lchild,key);elsereturn SearchBST(T->rchild,key);}void LeftBalance_div(BSTree &p,int &shorter) //删除结点时左平衡旋转处理{BSTree p1,p2;if(p->bf==1){ p->bf=0; shorter=1; }else if(p->bf==0){ p->bf=-1; shorter=0; }else{p1=p->rchild;if(p1->bf==0){L_Rotate(p);p1->bf=1; p->bf=-1; shorter=0;}else if(p1->bf==-1){L_Rotate(p);p1->bf=p->bf=0; shorter=1;}else{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 RightBalance_div(BSTree &p,int &shorter) //删除结点时右平衡旋转处理{BSTree 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){R_Rotate(p);p1->bf=-1; p->bf=1; shorter=0;}else if(p1->bf==1){R_Rotate(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(BSTree q,BSTree &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)RightBalance_div(r,shorter);}}int DeleteA VL(BSTree &p,int x,int &shorter) //平衡二叉树的删除操作{int k;BSTree q;if(p==NULL) { printf("不存在要删除的关键字!\n"); return 0;}else if(x<p->data){k=DeleteA VL(p->lchild,x,shorter);if(shorter==1)LeftBalance_div(p,shorter);return k;}else if(x>p->data){k=DeleteA VL(p->rchild,x,shorter);if(shorter==1)RightBalance_div(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)LeftBalance_div(p,shorter);p=q;}return 1;}}void PrintBST(BSTree T,int depth) {int i;if(T->rchild)PrintBST(T->rchild,depth+1);for(i=1;i<=depth;i++)printf(" ");printf("%d\n",T->data);if(T->lchild)PrintBST(T->lchild,depth+1); }。

相关文档
最新文档