完全二叉树操作演示

合集下载

判断一棵树是否为满二叉树的算法c语言

判断一棵树是否为满二叉树的算法c语言

判断一棵树是否为满二叉树的算法c语言判断一棵树是否为满二叉树的算法(C语言)满二叉树是一种特殊的二叉树,每个节点要么没有子节点,要么有两个子节点。

判断一棵树是否为满二叉树的算法可以通过以下步骤实现:1. 定义二叉树的数据结构在C语言中,可以使用结构体定义二叉树的节点。

每个节点包含一个数据域和两个指针域,分别指向左子节点和右子节点。

```cstruct TreeNode {int data;struct TreeNode* left;struct TreeNode* right;};```2. 实现判断函数编写一个递归函数,用于判断给定二叉树是否为满二叉树。

函数的输入参数为根节点指针,返回值为布尔类型。

```cint isFullBinaryTree(struct TreeNode* root) {// 如果根节点为空,则返回真if (root == NULL) {return 1;}// 如果只有一个子节点或没有子节点,则返回假if ((root->left == NULL && root->right != NULL) ||(root->left != NULL && root->right == NULL)) {return 0;}// 递归判断左子树和右子树return isFullBinaryTree(root->left) && isFullBinaryTree(root->right);}```3. 测试样例可以编写一些测试样例来验证判断函数的正确性。

例如,下面是一个满二叉树和一个非满二叉树的示例:```cint main() {// 满二叉树struct TreeNode* root1 = (struct TreeNode*)malloc(sizeof(struct TreeNode));root1->data = 1;root1->left = (struct TreeNode*)malloc(sizeof(struct TreeNode));root1->left->data = 2;root1->left->left = (struct TreeNode*)malloc(sizeof(struct TreeNode));root1->left->left->data = 4;root1->left->left->left = NULL;root1->left->left->right = NULL;root1->left->right = (struct TreeNode*)malloc(sizeof(struct TreeNode));root1->left->right->data = 5;root1->left->right->left = NULL;root1->left->right->right = NULL;root1->right = (struct TreeNode*)malloc(sizeof(struct TreeNode));root1->right->data = 3;root1->right->left = (struct TreeNode*)malloc(sizeof(struct TreeNode));root1->right->left->data = 6;root1->right->left->left = NULL;root1->right->left->right = NULL;root1->right->right = (struct TreeNode*)malloc(sizeof(struct TreeNode));root1->right->right->data = 7;root1->right->right->left = NULL;root1->right->right->right = NULL;// 非满二叉树struct TreeNode* root2 = (struct TreeNode*)malloc(sizeof(struct TreeNode));root2->data = 1;root2->left = (struct TreeNode*)malloc(sizeof(struct TreeNode));root2->left->data = 2;root2->left->left = (struct TreeNode*)malloc(sizeof(struct TreeNode));root2->left->left->data = 4;root2->left->left->left = NULL;root2->left->left->right = NULL;root2->right = (struct TreeNode*)malloc(sizeof(struct TreeNode));root2->right->data = 3;root2->right->left = NULL;root2->right->right = (struct TreeNode*)malloc(sizeof(struct TreeNode));root2->right->right->data = 7;root2->right->right->left = NULL;root2->right->right->right = NULL;// 判断是否为满二叉树if (isFullBinaryTree(root1)) {printf("root1是满二叉树\n");} else {printf("root1不是满二叉树\n");}if (isFullBinaryTree(root2)) {printf("root2是满二叉树\n");} else {printf("root2不是满二叉树\n");}return 0;}```运行上述代码,输出结果为:```root1是满二叉树root2不是满二叉树```根据以上算法和示例,我们可以判断一棵树是否为满二叉树。

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

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

平衡二叉树操作的演示1.需求分析本程序是利用平衡二叉树,实现动态查找表的基本功能:创建表,查找、插入、删除。

具体功能:(1)初始,平衡二叉树为空树,操作界面给出创建、查找、插入、删除、合并、分裂六种操作供选择。

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

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

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

(3)合并两棵平衡二叉树。

(4)把一棵二叉树分裂为两棵平衡二叉树,使得在一棵树中的所有关键字都小于或等于x,另一棵树中的任一关键字都大于x。

如下图:2.概要设计平衡二叉树是在构造二叉排序树的过程中,每当插入一个新结点时,首先检查是否因插入新结点而破坏了二叉排序树的平衡性,若是则找出其中的最小不平衡子树,在保持二叉排序树特性的前提下,调整最小不平衡子树中各结点之间的链接关系,进行相应的旋转,使之成为新的平衡子树。

具体步骤:(1)每当插入一个新结点,从该结点开始向上计算各结点的平衡因子,即计算该结点的祖先结点的平衡因子,若该结点的祖先结点的平衡因子的绝对值不超过1,则平衡二叉树没有失去平衡,继续插入结点;(2)若插入结点的某祖先结点的平衡因子的绝对值大于1,则找出其中最小不平衡子树的根结点;(3)判断新插入的结点与最小不平衡子树的根结点个关系,确定是那种类型的调整;(4)如果是LL型或RR型,只需应用扁担原理旋转一次,在旋转过程中,如果出现冲突,应用旋转优先原则调整冲突;如果是LR型或RL型,则需应用扁担原理旋转两次,第一次最小不平衡子树的根结点先不动,调整插入结点所在子树,第二次再调整最小不平衡子树,在旋转过程中,如果出现冲突,应用旋转优先原则调整冲突;(5)计算调整后的平衡二叉树中各结点的平衡因子,检验是否因为旋转而破坏其他结点的平衡因子,以及调整后平衡二叉树中是否存在平衡因子大于1的结点。

流程图3.详细设计二叉树类型定义:typedef int Status;typedef int ElemType;typedef struct BSTNode{ElemType data;int bf;struct BSTNode *lchild ,*rchild;} BSTNode,* BSTree;Status SearchBST(BSTree T,ElemType e)//查找void R_Rotate(BSTree &p)//右旋void L_Rotate(BSTree &p)//左旋void LeftBalance(BSTree &T)//插入平衡调整void RightBalance(BSTree &T)//插入平衡调整Status InsertAVL(BSTree &T,ElemType e,int &taller)//插入void DELeftBalance(BSTree &T)//删除平衡调整void DERightBalance(BSTree &T)//删除平衡调整Status Delete(BSTree &T,int &shorter)//删除操作Status DeleteAVL(BSTree &T,ElemType e,int &shorter)//删除操作void merge(BSTree &T1,BSTree &T2)//合并操作void splitBSTree(BSTree T,ElemType e,BSTree &T1,BSTree &T2)//分裂操作void PrintBSTree(BSTree &T,int lev)//凹入表显示附录源代码:#include<stdio.h>#include<stdlib.h>//#define TRUE 1//#define FALSE 0//#define OK 1//#define ERROR 0#define LH +1#define EH 0#define RH -1//二叉类型树的类型定义typedef int Status;typedef int ElemType;typedef struct BSTNode{ElemType data;int bf;//结点的平衡因子struct BSTNode *lchild ,*rchild;//左、右孩子指针} BSTNode,* BSTree;/*查找算法*/Status SearchBST(BSTree T,ElemType e){if(!T){return 0; //查找失败}else if(e == T->data ){return 1; //查找成功}else if (e < T->data){return SearchBST(T->lchild,e);}else{return SearchBST(T->rchild,e);}}//右旋void R_Rotate(BSTree &p){BSTree lc; //处理之前的左子树根结点lc = p->lchild; //lc指向的*p的左子树根结点p->lchild = lc->rchild; //lc的右子树挂接为*P的左子树lc->rchild = p;p = lc; //p指向新的根结点}//左旋void L_Rotate(BSTree &p){BSTree rc;rc = p->rchild; //rc指向的*p的右子树根结点p->rchild = rc->lchild; //rc的左子树挂接为*p的右子树rc->lchild = p;p = rc; //p指向新的根结点}//对以指针T所指结点为根结点的二叉树作左平衡旋转处理,//本算法结束时指针T指向新的根结点void LeftBalance(BSTree &T){BSTree lc,rd;lc=T->lchild;//lc指向*T的左子树根结点switch(lc->bf){ //检查*T的左子树的平衡度,并做相应的平衡处理case LH: //新结点插入在*T的左孩子的左子树,要做单右旋处理T->bf = lc->bf=EH;R_Rotate(T);break;case RH: //新结点插入在*T的左孩子的右子树上,做双旋处理rd=lc->rchild; //rd指向*T的左孩子的右子树根switch(rd->bf){ //修改*T及其左孩子的平衡因子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); //对*T的左子树作左旋平衡处理R_Rotate(T); //对*T作右旋平衡处理}}//右平衡旋转处理void RightBalance(BSTree &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 LH: T->bf=RH; rc->bf=EH;break;case EH: T->bf=rc->bf=EH;break;case RH: T->bf = EH; rc->bf=LH;break;}ld->bf=EH;R_Rotate(T->rchild);L_Rotate(T);}}//插入结点Status InsertAVL(BSTree &T,ElemType e,int &taller){//taller反应T长高与否if(!T){//插入新结点,树长高,置taller为trueT= (BSTree) malloc (sizeof(BSTNode));T->data = e;T->lchild = T->rchild = NULL;T->bf = EH;taller = 1;}else{if(e == T->data){taller = 0;return 0;}if(e < T->data){if(!InsertAVL(T->lchild,e,taller))//未插入return 0;if(taller)//已插入到*T的左子树中且左子树长高switch(T->bf){//检查*T的平衡度,作相应的平衡处理case LH:LeftBalance(T);taller = 0;break;case EH:T->bf = LH;taller = 1;break;case RH:T->bf = EH;taller = 0;break;}}else{if (!InsertAVL(T->rchild,e,taller)){return 0;}if(taller)//插入到*T的右子树且右子树增高switch(T->bf){//检查*T的平衡度case LH:T->bf = EH;taller = 0;break;case EH:T->bf = RH;taller = 1;break;case RH:RightBalance(T);taller = 0;break;}}}return 1;}void DELeftBalance(BSTree &T){//删除平衡调整BSTree lc,rd;lc=T->lchild;switch(lc->bf){case LH:T->bf = EH;//lc->bf= EH;R_Rotate(T);break;case EH:T->bf = EH;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 DERightBalance(BSTree &T) //删除平衡调整{BSTree rc,ld;rc=T->rchild;switch(rc->bf){case RH:T->bf= EH;//rc->bf= EH;L_Rotate(T);break;case EH:T->bf= EH;//rc->bf= EH;L_Rotate(T);break;case LH:ld=rc->lchild;switch(ld->bf){case LH: T->bf=RH; rc->bf=EH;break;case EH: T->bf=rc->bf=EH;break;case RH: T->bf = EH; rc->bf=LH;break;}ld->bf=EH;R_Rotate(T->rchild);L_Rotate(T);}}void SDelete(BSTree &T,BSTree &q,BSTree &s,int &shorter){if(s->rchild){SDelete(T,s,s->rchild,shorter);if(shorter)switch(s->bf){case EH:s->bf = LH;shorter = 0;break;case RH:s->bf = EH;shorter = 1;break;case LH:DELeftBalance(s);shorter = 0;break;}return;}T->data = s->data;if(q != T)q->rchild = s->lchild;elseq->lchild = s->lchild;shorter = 1;}//删除结点Status Delete(BSTree &T,int &shorter){ BSTree q;if(!T->rchild){q = T;T = T->lchild;free(q);shorter = 1;}else if(!T->lchild){q = T;T= T->rchild;free(q);shorter = 1;}else{SDelete(T,T,T->lchild,shorter);if(shorter)switch(T->bf){case EH:T->bf = RH;shorter = 0;break;case LH:T->bf = EH;shorter = 1;break;case RH:DERightBalance(T);shorter = 0;break;}}return 1;}Status DeleteAVL(BSTree &T,ElemType e,int &shorter){ int sign = 0;if (!T){return sign;}else{if(e == T->data){sign = Delete(T,shorter);return sign;}else if(e < T->data){sign = DeleteAVL(T->lchild,e,shorter);if(shorter)switch(T->bf){case EH:T->bf = RH;shorter = 0;break;case LH:T->bf = EH;shorter = 1;break;case RH:DERightBalance(T);shorter = 0;break;}return sign;}else{sign = DeleteAVL(T->rchild,e,shorter);if(shorter)switch(T->bf){case EH:T->bf = LH;shorter = 0;break;case RH:T->bf = EH;break;case LH:DELeftBalance(T);shorter = 0;break;}return sign;}}}//合并void merge(BSTree &T1,BSTree &T2){int taller = 0;if(!T2)return;merge(T1,T2->lchild);InsertAVL(T1,T2->data,taller);merge(T1,T2->rchild);}//分裂void split(BSTree T,ElemType e,BSTree &T1,BSTree &T2){ int taller = 0;if(!T)return;split(T->lchild,e,T1,T2);if(T->data > e)InsertAVL(T2,T->data,taller);elseInsertAVL(T1,T->data,taller);split(T->rchild,e,T1,T2);}//分裂void splitBSTree(BSTree T,ElemType e,BSTree &T1,BSTree &T2){ BSTree t1 = NULL,t2 = NULL;split(T,e,t1,t2);T1 = t1;T2 = t2;return;}//构建void CreatBSTree(BSTree &T){int num,i,e,taller = 0;printf("输入结点个数:");scanf("%d",&num);printf("请顺序输入结点值\n");for(i = 0 ;i < num;i++){printf("第%d个结点的值",i+1);scanf("%d",&e);InsertAVL(T,e,taller) ;}printf("构建成功,输入任意字符返回\n");getchar();getchar();}//凹入表形式显示方法void PrintBSTree(BSTree &T,int lev){int i;if(T->rchild)PrintBSTree(T->rchild,lev+1);for(i = 0;i < lev;i++)printf(" ");printf("%d\n",T->data);if(T->lchild)PrintBSTree(T->lchild,lev+1);void Start(BSTree &T1,BSTree &T2){int cho,taller,e,k;taller = 0;k = 0;while(1){system("cls");printf(" 平衡二叉树操作的演示 \n\n");printf("********************************\n");printf(" 平衡二叉树显示区 \n");printf("T1树\n");if(!T1 )printf("\n 当前为空树\n");else{PrintBSTree(T1,1);}printf("T2树\n");if(!T2 )printf("\n 当前为空树\n");elsePrintBSTree(T2,1);printf("\n********************************************************************* *********\n");printf("T1操作:1.创建 2.插入 3.查找 4.删除 10.分裂\n");printf("T2操作:5.创建 6.插入 7.查找 8.删除 11.分裂\n");printf(" 9.合并 T1,T2 0.退出\n");printf("*********************************************************************** *******\n");printf("输入你要进行的操作:");scanf("%d",&cho);switch(cho){case 1:CreatBSTree(T1);break;case 2:printf("请输入要插入关键字的值");scanf("%d",&e);InsertAVL(T1,e,taller) ;break;case 3:printf("请输入要查找关键字的值");scanf("%d",&e);if(SearchBST(T1,e))printf("查找成功!\n");elseprintf("查找失败!\n");printf("按任意键返回87"); getchar();getchar();break;case 4:printf("请输入要删除关键字的值"); scanf("%d",&e);if(DeleteAVL(T1,e,k))printf("删除成功!\n");elseprintf("删除失败!\n");printf("按任意键返回");getchar();getchar();break;case 5:CreatBSTree(T2);break;case 6:printf("请输入要插入关键字的值"); scanf("%d",&e);InsertAVL(T2,e,taller) ;break;case 7:printf("请输入要查找关键字的值"); scanf("%d",&e);if(SearchBST(T2,e))printf("查找成功!\n");elseprintf("查找失败!\n");printf("按任意键返回");getchar();getchar();break;case 8:printf("请输入要删除关键字的值"); scanf("%d",&e);if(DeleteAVL(T2,e,k))printf("删除成功!\n");elseprintf("删除失败!\n");printf("按任意键返回");getchar();getchar();break;case 9:merge(T1,T2);T2 = NULL;printf("合并成功,按任意键返回"); getchar();getchar();break;case 10:printf("请输入要中间值字的值"); scanf("%d",&e);splitBSTree(T1,e,T1,T2) ;printf("分裂成功,按任意键返回"); getchar();getchar();break;case 11:printf("请输入要中间值字的值"); scanf("%d",&e);splitBSTree(T2,e,T1,T2) ;printf("分裂成功,按任意键返回"); getchar();getchar();break;case 0:system("cls");exit(0);}}}main(){BSTree T1 = NULL;BSTree T2 = NULL;Start(T1,T2);}。

二叉树的基本操作

二叉树的基本操作

二叉树的基本操作二叉树是一种常见的数据结构,它由节点组成,每个节点最多有两个子节点。

二叉树在计算机领域中得到广泛应用,它的基本操作包括插入、删除、查找、遍历等。

1.插入操作:二叉树的插入操作是将一个新的节点添加到已有的二叉树中的过程。

插入操作会按照一定规则将新节点放置在正确的位置上。

插入操作的具体步骤如下:-首先,从根节点开始,比较新节点的值与当前节点的值的大小关系。

-如果新节点的值小于当前节点的值,则将新节点插入到当前节点的左子树中。

-如果新节点的值大于当前节点的值,则将新节点插入到当前节点的右子树中。

-如果当前节点的左子树或右子树为空,则直接将新节点插入到该位置上。

-如果当前节点的左子树和右子树都不为空,则递归地对左子树或右子树进行插入操作。

2.删除操作:二叉树的删除操作是将指定节点从二叉树中删除的过程。

删除操作有以下几种情况需要考虑:-如果待删除节点是叶子节点,则直接将其从二叉树中删除即可。

-如果待删除节点只有一个子节点,则将其子节点替换为待删除节点的位置即可。

-如果待删除节点有两个子节点,则需要找到其左子树或右子树中的最大节点或最小节点,将其值替换为待删除节点的值,然后再删除最大节点或最小节点。

3.查找操作:二叉树的查找操作是在二叉树中查找指定值的节点的过程。

查找操作的具体步骤如下:-从根节点开始,将待查找值与当前节点的值进行比较。

-如果待查找值等于当前节点的值,则返回该节点。

-如果待查找值小于当前节点的值,则在当前节点的左子树中继续查找。

-如果待查找值大于当前节点的值,则在当前节点的右子树中继续查找。

-如果左子树或右子树为空,则说明在二叉树中找不到该值。

4.遍历操作:二叉树的遍历操作是按照一定规则依次访问二叉树中的每个节点。

有三种常用的遍历方式:- 前序遍历(Preorder Traversal):先访问根节点,然后递归地前序遍历左子树和右子树。

- 中序遍历(Inorder Traversal):先递归地中序遍历左子树,然后访问根节点,最后递归地中序遍历右子树。

详解平衡二叉树

详解平衡二叉树

一、平衡二叉树的概念平衡二叉树(Balanced binary tree)是由阿德尔森-维尔斯和兰迪斯(Adelson-Velskii and Landis)于1962年首先提出的,所以又称为AVL树。

定义:平衡二叉树或为空树,或为如下性质的二叉排序树:(1)左右子树深度之差的绝对值不超过1;(2)左右子树仍然为平衡二叉树.平衡因子BF=左子树深度-右子树深度.平衡二叉树每个结点的平衡因子只能是1,0,-1。

若其绝对值超过1,则该二叉排序树就是不平衡的。

如图所示为平衡树和非平衡树示意图:二、平衡二叉树算法思想若向平衡二叉树中插入一个新结点后破坏了平衡二叉树的平衡性。

首先要找出插入新结点后失去平衡的最小子树根结点的指针。

然后再调整这个子树中有关结点之间的链接关系,使之成为新的平衡子树。

当失去平衡的最小子树被调整为平衡子树后,原有其他所有不平衡子树无需调整,整个二叉排序树就又成为一棵平衡二叉树。

失去平衡的最小子树是指以离插入结点最近,且平衡因子绝对值大于1的结点作为根的子树。

假设用A表示失去平衡的最小子树的根结点,则调整该子树的操作可归纳为下列四种情况。

1)LL型平衡旋转法由于在A的左孩子B的左子树上插入结点F,使A的平衡因子由1增至2而失去平衡。

故需进行一次顺时针旋转操作。

即将A的左孩子B向右上旋转代替A作为根结点,A向右下旋转成为B的右子树的根结点。

而原来B的右子树则变成A的左子树。

(2)RR型平衡旋转法由于在A的右孩子C 的右子树上插入结点F,使A的平衡因子由-1减至-2而失去平衡。

故需进行一次逆时针旋转操作。

即将A的右孩子C向左上旋转代替A作为根结点,A向左下旋转成为C的左子树的根结点。

而原来C的左子树则变成A的右子树。

(3)LR型平衡旋转法由于在A的左孩子B的右子数上插入结点F,使A的平衡因子由1增至2而失去平衡。

故需进行两次旋转操作(先逆时针,后顺时针)。

即先将A结点的左孩子B的右子树的根结点D向左上旋转提升到B结点的位置,然后再把该D结点向右上旋转提升到A结点的位置。

判断二叉树是否为完全二叉树的实例

判断二叉树是否为完全二叉树的实例

判断二叉树是否为完全二叉树的实例判断二叉树是否为完全二叉树的实例完全二叉树是指除了最后一层之外,其他每一层的结点数都是满的,今天店铺为大家整理的判断二叉树是否为完全二叉树的'实例,仅供学习参考,欢迎大家阅读浏览!完全二叉树特点完全二叉树是指除了最后一层之外,其他每一层的结点数都是满的。

最后一层如果也满了,是一颗满二叉树,也是完全二叉树。

最后一层如果不满,缺少的结点也全部的集中在左边,那也是一颗完全二叉树。

import java.util.*;class TreeNode {int val = 0;TreeNode left = null;TreeNode right = null;public TreeNode(int val) {this.val = val;}}public class CheckCompletion {public boolean checking(TreeNode root) {Queue<TreeNode> queue = new LinkedList<TreeNode>();boolean leaf = false; // 叶子结点TreeNode left;TreeNode right;queue.add(root);while (!queue.isEmpty()) {root = queue.poll();left = root.left;right = root.right;if ((leaf&&(left!=null||right!=null)) || (left==null&&right!=null)) {// 如果之前层遍历的结点没有右孩子,且当前的结点有左或右孩子,直接返回false// 如果当前结点有右孩子却没有左孩子,直接返回falsereturn false;}if (left != null) {queue.offer(root.left);}if (right != null) {queue.offer(root.right);}else {leaf = false; // 如果当前结点没有右孩子,那么之后层遍历到的结点必须为叶子结点}}return true;}}感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!【判断二叉树是否为完全二叉树的实例】。

《二叉树模型》课件

《二叉树模型》课件

二叉树的分类
01 满二叉树
如果一个二叉树的每个节点都有两个子节点,则 该二叉树称为满二叉树。
02 完全二叉树
如果一个二叉树的最后一层是满的,且除了最后 一层外,其他各层的节点数达到最大,则该二叉 树称为完全二叉树。
03 平衡二叉树
平衡二叉树是一种特殊的完全二叉树,它的左右 子树的高度差不超过1。
二叉树的应用场景
详细描述
在n叉树模型中,每个节点可以拥有任意数 量的子节点,而不仅仅是两个。这种模型在 处理具有多个分支的数据结构时非常有用, 例如决策树和知识图谱。n叉树模型在搜索 、排序和数据压缩等领域有广泛应用。
B树模型
要点一
总结词
B树模型是一种自平衡的多路搜索树,用于数据库和文件系 统的索引。
要点二
详细描述
详细描述
二叉树的插入操作包括节点的添加和位置调整两个步骤。在添加节点时,需要找到合适 的位置将其插入到二叉树中,并保持二叉树的平衡性。位置调整是为了维护二叉树的性
质,确保每个节点的左子树和右子树的高度差不超过1。
插入操作的时间复杂度
总结词
插入操作的时间复杂度取决于具体的实现方式和数据结构。
详细描述
在平衡二叉树中,插入操作的时间复杂度为O(log n),其中n为二叉树中节点的数量。而在一般的二 叉树中,插入操作的时间复杂度可能达到O(n),因为可能需要遍历整棵树才能找到合适的位置插入新 节点。因此,选择合适的二叉树数据结构和算法对于提高插入操作的效率至关重要。
05
二叉树算法的应用
堆排序算法
平衡二叉树的性质:平衡二叉树具有以下性质:1)它的左右子树的高度差不超过1;2)它的左 子树和右子树都是平衡二叉树;3)它的左子树和右子树的节点数相差不超过1。

二叉树的顺序存储及基本操作

二叉树的顺序存储及基本操作

二叉树的顺序存储及基本操作二叉树的顺序存储是将树中的节点按照完全二叉树从上到下、从左到右的顺序依次存储到一个一维数组中,采用这种方式存储的二叉树也被称为完全二叉树。

一、在使用顺序存储方式时,可以使用以下公式来计算一个节点的左右子节点和父节点:
1. 左子节点:2i+1(i为父节点的在数组中的下标)
2. 右子节点:2i+2
3. 父节点:(i-1)/2(i为子节点在数组中的下标)
二、基本操作:
1. 创建二叉树:按照上述公式将节点存储到数组中。

2. 遍历二叉树:可采用递归或非递归方式,进行前序、中序、后序、层次遍历。

3. 插入节点:先将节点插入到数组末尾,然后通过比较节点和其父节点的大小,进行上浮操作直到满足二叉树的性质。

4. 删除节点:先将待删除节点和最后一个节点交换位置,然后通过比较交换后的节点和其父节点的大小,进行下沉操作直到满足二
叉树的性质。

5. 查找节点:根据节点值进行查找,可采用递归或非递归方式。

6. 修改节点:根据节点值进行查找,然后进行修改操作。

基本二叉树知识讲解

基本二叉树知识讲解

基本二叉树知识讲解一、有关二叉树的学习性质1:二叉树上叶子结点数等于度为2的结点数加1。

性质2:二叉树的第i层上至多有2的i次方减1个结点(i>=1)。

性质3:深度为h的二叉树至多有2的h次方减1个结点。

满二叉树:在一棵二叉树中,当第i层的结点树为2的i次方减1个时,称此层的结点数是满的。

当一棵二叉树中的每一层都满时,称此树为满二叉树。

特性:除叶子结点以外的其他的结点的度皆为2,且叶子结点在同一层上。

深度为h的满二叉树中的结点数为2的h次方减1。

性质4:设含有n个结点的完全二叉树的深度为k,则k=(int)(log2n)+1,即深度k等于log2n的整数部分再加1。

二叉树的存储结构1:顺序存储结构二叉树的顺序存储结构类型定义如下:#define TREEMINSIZE 10typedef struct{BTreeDT(数据类型) *base;int spacesize;BTreeDT nullvalue;}SeqTree;2:链式存储结构(一般的二叉树主要采用链式存储结构通常有二叉链表和三叉链表两种形式)1>二叉链表存储结构二叉链表中的每个结点由data,lchild和rchild三个域组成,定义如下:typedef struct bkbtnode{BTreeDT data;struct bkbtnode *lchild;struct bkbtnode *rchild;}BTNode,*BKBTree;在二叉链表中,查找某结点的孩子很容易实现,但查找某结点的双亲不方便。

一棵喊有n个结点的二叉树采用二叉链表存储时,将有2n-(n-1)=n+1个指针域是空的。

2>三叉链表存储结构typedef struct tkbtnode{BTreeDT data;struct tkbtnode *lchild;struct tkbtnode *rchild;struct tkbtnode *parent;}TKBTNode,*TKBTree;其中,parent域存放该结点双亲的指针。

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

安徽省巢湖学院计算机与信息工程学院课程设计报告课程名称《数据结构》课题名称完全二叉树操作演示专业班级计算机科学与技术专升本1班学号********、********、********姓名李鹏王帅李泳波联系方式指导教师严小燕完成日期: 2014年12月27 日目录1 数据结构课程设计任务书 (1)1.1题目 (1)1.2目的 (1)1.3要求 (1)2 总体设计 (1)2.1功能模块设计 (1)2.2所有功能模块流程图 (1)3 详细设计 (2)3.1程序中所采用的数据结构及存储结构的说明 (2)3.2算法设计思想 (3)3.3主要的功能函数 (3)4 调试与测试 (3)4.1调试方法与步骤 (4)4.2测试结果分析与讨论 (4)4.3测试过程中遇到的主要问题及采取的解决措施 (5)5 时间复杂度分析 (6)6 程序清单 (6)7 总结 (12)参考文献 (13)1 数据结构课程设计任务书1.1题目完全二叉树操作演示1.2目的(1)掌握二叉树的概念和性质。

(2)掌握完全二叉树存储结构。

(3)掌握完全二叉树的基本操作。

1.3 要求(1)创建完全二叉树(用字母表示节点)(用顺序方式存储)。

(2)求二叉树的深度和叶子结点数。

(3)实现二叉树的前序、中序、后序和层次遍历。

(4)查找给定结点的双亲、祖先和左右孩子节点。

2 总体设计2.1 功能模块设计根据课程设计题目的功能要求,各个功能模块的组成框图如图1:图 1 功能组成框图2.2 所有功能模块流程图设计好功能模块后,各个模块的关系如下图2:图 2 流程图3 详细设计3.1程序中所采用的数据结构及存储结构的说明(1)整个程序采用结构体与顺序表相结合的编程方法一共完成了7个功能。

在你输入错误时有报错消息,这样使整个程序运行起来更加完整。

程序中有若干个子函数被主函数调用执行。

结构体定义如下:#define MAX 100 //定义100个节点typedef struct{char dat; //节点信息}node;typedef struct Tree //节点组成树{int length;node *r; //指向根节点}Tree;3.2 算法设计思想完全二叉树具有以下几个性质,由此可设计出相应算法。

性质1 完全二叉树约定编号从根节点起,自上而下,自左自由。

由此设计出顺序存储结构且进行层次遍历时,只需输出顺序表中存储的元素即可。

性质2 具有n 个结点的完全二叉树的深度为 。

由此设计出深度计算函数。

性质3 完全二叉树第i 层上的结点数目最多为2i-1(i≥1)。

由此设计出每层节点个数函数,在显示完全二叉树时可以找到其最左边的孩子节点。

性质4 在完全二叉树中,若某个结点没有左孩子,则它一定没有右孩子,即该结点必是叶结点且叶子节点个数为(n+1)/2。

由此设计出叶子节点函数。

性质5 在完全二叉树中,若根节点为i ,则左孩子节点为2i,右孩子节点为2i+1。

由此采用递归思想,可以对完全二叉树进行前序、中序、后序遍历和给定节点找其双亲及孩子。

3.3主要的功能函数CreatTree(Tree &t) //创建完全二叉树 LevCount(int n) //统计每层最多节点个数 OutputTree(Tree &t) //显示完全二叉树 Depth(Tree &t) //求树深 Leaf(Tree &t) //叶子节点PreOrder(Tree &t,int r) //先序遍历 InOrder(Tree &t,int r) //中序遍历 PostOrder(Tree &t,int r) //后序遍历 LeOrder(Tree &t) //层次遍历Search(Tree &t,char q) //查找给定结点的双亲、左右孩子 完善以上函数,就可以设计出完全二叉树的操作了。

4 调试与测试1log 2 n4.1调试方法与步骤第一步:建立完全二叉树,输入节点个数和节点。

第二步:选择要操作的对象,比如显示完全二叉树,按下电脑键盘1。

查找双亲及孩子功能函数在操作时需要输入信息,按照相应提示输入相应信息即可运行,输入不对时,程序会有报错提示信息。

4.2测试结果分析与讨论假定完全二叉树节点数为9个,节点信息为a、b、c、d、e、f、g、h、i。

操作结果如下图所示:(1)操作界面图3 操作界面(2)创建完全二叉树图4 创建完全二叉树(3)显示完全二叉树图5 显示完全二叉树(4)完全二叉树深度图6 完全二叉树深度(5)完全二叉树层次遍历图7 完全二叉树层次遍历(6)完全二叉树前序、中序、后序图8 前序、中序、后序遍历(7)查找给定节点双亲及孩子图9 查找给定节点双亲及孩子(8)完全二叉树叶子节点数图10 节点数4.3 测试过程中遇到的主要问题及采取的解决措施在建立完全二叉树时操作不当会出现程序错误。

如下图:图11 错误界面导致以上错误的原因是,再输入第一个字母元素时,不能空格,程序中的getchar()函数只能接收上一个空格字符,即输入节点产生的空格,解决方法是重新编译运行程序按要求输入即可。

5 时间复杂度分析这里主要分析查找节点时的时间复杂度,当给定节点时,需要在顺序表中进行一一比对查找,即顺序查找,那么最坏的情况就是找最后一个叶子节点了,这就跟表长有关系了,所以时间复杂度为n=length。

6 程序清单#include<stdio.h>#include<stdlib.h>#include<string.h>#define MAX 100 //定义100个节点typedef struct{char dat; //节点信息}node;typedef struct Tree //节点组成树{int length;node *r; //指向根节点}Tree;int CreatTree(Tree &t){int i;t.r =(node *)malloc(MAX*sizeof(node));//r[MAX]printf("请输入完全二叉树节点个数,输入后继续:");scanf("%d",&t.length);printf("请输入完全二叉树节点,以字母空格隔开且不要以空格开头:");for(i=0;i<t.length;i++){getchar();scanf("%c",&t.r[i+1].dat);}return 1;}int LevCount(int n) //统计每层最多节点个数{int p=1;for(int i=1;i<=n;i++)p=p*2;return p;}void OutputTree(Tree &t) //显示完全二叉树{int k=0,n=t.length;//求树的层数 Kwhile(n){k++;n=n/2;} //层数控制行每层节点个数控制列for(inti=1;i<=k;i++)//j<LevCount(i)-LevCount(i-1)&&LevCount(i-1)+j<=t.length { //判断条件是每层节点个数且以最左边孩子节点开始不小于表长for(intj=0;j<LevCount(i)-LevCount(i-1)&&LevCount(i-1)+j<=t.length;j++)printf("%2c",t.r[LevCount(i-1)+j].dat); //输出每层各个节点printf("\n");}}void Depth(Tree &t) //求树深{int k=0,n=t.length;while(n){k++;n=n/2;}printf("二叉树深度:%2d\n",k);}void Leaf(Tree &t) //叶子节点{int lef;lef=(t.length+1)/2;printf("叶子节点个数:%2d\n",lef);}void PreOrder(Tree &t,int r) //先序遍历 DLR{if(t.length<r) return;printf("%c",t.r[r].dat);PreOrder(t,2*r);PreOrder(t,2*r+1);}void InOrder(Tree &t,int r) //中序遍历 LDR{if (t.length<r) return;InOrder(t,2*r);printf("%c",t.r[r].dat);InOrder(t,2*r+1);}void PostOrder(Tree &t,int r) //后序遍历 LRD{if(t.length<r)return;PostOrder(t,2*r);PostOrder(t,2*r+1);printf("%c",t.r[r].dat);}void LeOrder(Tree &t) //层次遍历{int i;for(i=0;i<t.length;i++)printf("%c",t.r[i+1].dat);printf("\n");}void Search(Tree &t,char q) //查找给定结点的双亲、左右孩子{bool flag=false;int i;printf("请输入查找节点:");getchar();scanf("%c",&q);for(i=1;i<=t.length;i++){if(t.r[i].dat==q) //找到给定节点下标且默认节点0号单元无节点{if(i/2==0) //根节点无双亲printf("此节点无双亲");elseprintf("此节点的双亲: %c",t.r[i/2].dat);if(2*i>t.length) //左孩子下标值大于表长,肯定无孩子 printf("此节点无左右孩子");else{printf(" 此节点左孩子: %c",t.r[2*i].dat);if(2*i+1>t.length) //右孩子下标值大于表长,只是无右孩子printf(" 此节点无右孩子");else{printf(" 此节点右孩子: %c",t.r[2*i+1].dat);}}flag=true;break;}}if(flag==false)printf("二叉树中没有此节点\n");printf("\n");}void menu(){printf("*****************************菜单************************************\n"); printf(" \n"); printf(" \n"); printf(" 1. 创建完全二叉树 2. 显示完全二叉树\n"); printf(" \n"); printf(" 3. 完全二叉树深度 4. 完全二叉树层次遍历\n"); printf(" \n"); printf(" 5. 完全二叉树的前序、中序、后序 6. 查找给定结点双亲、左右孩子\n");printf(" \n"); printf(" 7.完全二叉树叶子结点数8. 退出系统\n"); printf(" \n"); printf(" \n"); printf(" 请先对菜单1 操作后,再进行其它操作\n"); }void main(){Tree t;int chose;char p;menu();while(1){printf("请选择操作:");scanf("%d",&chose);switch (chose){case 1: CreatTree(t);printf("\n"); break; //建树case 2: OutputTree(t);printf("\n"); break; //显示树case 3: Depth(t);printf("\n"); break; //深度case 4: printf("层次遍历:");LeOrder(t); printf("\n"); break;case 5: printf("先序遍历:");PreOrder(t,1); printf("\n");printf("中序遍历:"); InOrder(t,1);printf("\n");printf("后序遍历:"); PostOrder(t,1);printf("\n"); printf("\n"); break;case6: Search(t,p);printf("\n"); break; //查找case 7: Leaf(t);printf("\n"); break; //叶子case 8: printf(" 谢谢你的使用\n");exit(0);break;default: printf("输入错误,请重新选择\n"); break;}}}7 总结通过这次课程设计,让我们知道了很多,特别是平时做作业时,在很多问题上一知半解就过去了的问题,在操作中都不太懂。

相关文档
最新文档