实验5 二叉搜索树的基本操作(大作业)
数据结构-实验五-二叉树的操作
数据结构实验报告实验五二叉树的操作班级:12卓越6班学号:***********名:***任课教师:***计算机与信息工程学院2014年5月13 日实验五二叉树的操作一、实验目的1.进一步掌握指针变量、动态变量的含义;2.掌握二叉树的结构特征,以及各种存储结构的特点及适用范围;3.掌握用指针类型描述、访问和处理二叉树的运算。
二、实验要求1.按实验内容编写实验的程序,主程序以菜单形式运行。
2.上机调试运行本程序。
3.保存和打印出程序的运行结果,并结合程序进行分析。
4.提交源程序和运行结果。
三、实验内容1.创建以二叉链表作存储结构的二叉树;2.按中序遍历二叉树;3.按层次遍历二叉树;4.计算二叉树的单枝结点数;5.交换二叉树的左右子树。
解://声明类BiTree及定义结构BiNode,文件名为bitree.h#ifndef BITREE_H#define BITREE_H//int num;template <class T>struct BiNode //二叉树的结点结构{T data;BiNode<T> *lchild, *rchild;};template <class T>class BiTree{public:BiTree( ); //构造函数,初始化一棵二叉树,其前序序列由键盘输入~BiTree(void); //析构函数,释放二叉链表中各结点的存储空间BiNode<T>* Getroot(); //获得指向根结点的指针void PreOrder(BiNode<T> *root); //前序遍历二叉树void InOrder(BiNode<T> *root); //中序遍历二叉树void PostOrder(BiNode<T> *root); //后序遍历二叉树void LeverOrder(BiNode<T> *root); //层序遍历二叉树int depth(BiNode<T> *root); //求二叉树的深度void nodenum(BiNode<T> *root); //求二叉树的结点个数void leafnum(BiNode<T> *root); //求二叉树的叶子结点个数void empty( ); //判断二叉树是否为空int printnum( ); // 输出(全部、叶子或单分支)结点数void sbnodenum(BiNode<T> *root); //求二叉树的单分支结点个数void exchangetree(BiNode<T> *root); //交换二叉树的左右子树private:BiNode<T> *root; //指向根结点的头指针BiNode<T> *p;BiNode<T> *Creat( ); //有参构造函数调用void Release(BiNode<T> *root); //析构函数调用int num;};#endif//定义类中的成员函数,文件名为bitree.cpp#include<iostream>#include<string>#include"bietree.h"using namespace std;/**前置条件:二叉树不存在*输入:无*功能:构造一棵二叉树*输出:无*后置条件:产生一棵二叉树*/template<class T>BiTree<T>::BiTree( ){this->num=0;this->root = Creat( );}/**前置条件:二叉树已存在*输入:无*功能:释放二叉链表中各结点的存储空间*输出:无*后置条件:二叉树不存在*/template<class T>BiTree<T>::~BiTree(void){Release(root);}*前置条件:二叉树已存在*输入:无*功能:获取指向二叉树根结点的指针*输出:指向二叉树根结点的指针*后置条件:二叉树不变*/template<class T>BiNode<T>* BiTree<T>::Getroot( ){return root;}/**前置条件:二叉树已存在*输入:无*功能:前序遍历二叉树*输出:二叉树中结点的一个线性排列*后置条件:二叉树不变*/template<class T>void BiTree<T>::PreOrder(BiNode<T> *root) {if(root==NULL) return;else{cout<<root->data<<" ";PreOrder(root->lchild);PreOrder(root->rchild);}}*前置条件:二叉树已存在*输入:无*功能:中序遍历二叉树*输出:二叉树中结点的一个线性排列*后置条件:二叉树不变*/template <class T>void BiTree<T>::InOrder (BiNode<T> *root){if (root==NULL) return; //递归调用的结束条件else{InOrder(root->lchild); //中序递归遍历root的左子树cout<<root->data<<" "; //访问根结点的数据域InOrder(root->rchild); //中序递归遍历root的右子树}}/**前置条件:二叉树已存在*输入:无*功能:后序遍历二叉树*输出:二叉树中结点的一个线性排列*后置条件:二叉树不变*/template <class T>void BiTree<T>::PostOrder(BiNode<T> *root){if (root==NULL) return; //递归调用的结束条件else{PostOrder(root->lchild); //后序递归遍历root的左子树PostOrder(root->rchild); //后序递归遍历root的右子树cout<<root->data<<" "; //访问根结点的数据域}}/**前置条件:二叉树已存在*输入:无*功能:层序遍历二叉树*输出:二叉树中结点的一个线性排列*后置条件:二叉树不变*/template <class T>void BiTree<T>::LeverOrder(BiNode<T> *root){const int MaxSize = 100;int front = 0;int rear = 0; //采用顺序队列,并假定不会发生上溢BiNode<T>* Q[MaxSize];BiNode<T>* q;if (root==NULL) return;else{Q[rear++] = root;while (front != rear){q = Q[front++];cout<<q->data<<" ";if (q->lchild != NULL) Q[rear++] = q->lchild;if (q->rchild != NULL) Q[rear++] = q->rchild;}}}/**前置条件:空二叉树*输入:数据ch;*功能:初始化一棵二叉树,构造函数调用*输出:无*后置条件:产生一棵二叉树*/template <class T>BiNode<T>* BiTree<T>::Creat( ){BiNode<T>* root;T ch;cout<<"请输入创建一棵二叉树的结点数据"<<endl;cin>>ch;if (ch=="#") root = NULL;else{root = new BiNode<T>; //生成一个结点root->data=ch;root->lchild = Creat( ); //递归建立左子树root->rchild = Creat( ); //递归建立右子树}return root;}/**前置条件:二叉树已经存在*输入:无*功能:释放二叉树的存储空间,析构函数调用*输出:无*后置条件:二叉树不存在*/template<class T>void BiTree<T>::Release(BiNode<T>* root){if (root != NULL){Release(root->lchild); //释放左子树Release(root->rchild); //释放右子树delete root;}}/**前置条件:二叉树已经存在*输入:无*功能:求二叉树的深度*输出:二叉树的深度*后置条件:二叉树不变*/template<class T>int BiTree<T>::depth(BiNode<T> *root){int n,m;if(root==NULL) return 0;else{n=depth(root->lchild); //左子树的深度m=depth(root->rchild); //右子树的深度if (n>m)return n+1;elsereturn m+1;}}/**前置条件:二叉树已经存在*输入:无*功能:求二叉树的结点个数*输出:二叉树的结点个数*后置条件:二叉树不变*/template<class T>void BiTree<T>::nodenum(BiNode<T> *root){if(root==NULL) return;else{num++;nodenum(root->lchild); //左子树的结点个数nodenum(root->rchild); //右子树的结点个数}}*前置条件:二叉树已经存在*输入:无*功能:求二叉树2 的叶子结点个数*输出:二叉树的叶子结点个数*后置条件:二叉树不变*/template<class T>void BiTree<T>::leafnum(BiNode<T> *root){if(root==NULL) return;else{if(!(root->lchild) && !(root->rchild)) //判断是否为叶子结点num++;leafnum(root->lchild); //左子树中的叶子结点个数leafnum(root->rchild); //右子树中的叶子结点个数}}/*将全局变量num初始化为0*/template<class T>void BiTree<T>::empty( ){num=0;}输出全局变量num的值*/template<class T>int BiTree<T>::printnum( ){return num;}/**前置条件:二叉树已经存在*输入:无*功能:求二叉树的单分支结点个数*输出:二叉树的单分支结点个数*后置条件:二叉树不变*/template<class T>void BiTree<T>::sbnodenum(BiNode<T> *root){if(root==NULL) return;else{if((!(root->lchild) && (root->rchild))||((root->lchild) && !(root->rchild))) //判断是否为叶子结点num++;sbnodenum(root->lchild); //左子树中的叶子结点个数sbnodenum(root->rchild); //右子树中的叶子结点个数}}/**前置条件:二叉树已经存在*输入:无*功能:交换二叉树的左右子树*输出:无*后置条件:二叉树左右子树交换*/template<class T>void BiTree<T>::exchangetree(BiNode<T> *root){if(root==NULL) return;else{if((root->rchild)&&(root->lchild)) //判断左右叶子结点都存在{ p=root->lchild;root->lchild=root->rchild;root->rchild=p;}exchangetree(root->lchild); //左子树中的叶子结点个数exchangetree(root->rchild); //右子树中的叶子结点个数}}/* BiNode<T> * Q[20];BiNode<T> *q;int front=-1;int rear=-1;int n=0;int m=0;Q[++rear]=root;if(root==NULL)cout<<0;else{while(front!=rear){q=Q[++front];if(q->lchild==NULL && q->rchild!=NULL)m++;if(q->lchild!=NULL && q->rchild==NULL)n++;if(q->lchild!=NULL) Q[++rear]=q->lchild;if(q->rchild!=NULL) Q[++rear]=q->rchild;}}cout<<"单分支节点的个数为:"<<m+n<<endl;*///二叉树的主函数,文件名为bitreemain.cpp#include<iostream>#include<string>#include"bietree.cpp"using namespace std;void main(){BiTree<string> bt; //创建一棵树BiNode<string>* root = bt.Getroot( ); //获取指向根结点的指针int s=-1;while(s!=0){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<<"0.退出"<<endl;cin>>s;switch(s){ case 1:bt.PreOrder(root);cout<<endl;break;case 2:bt.InOrder(root);cout<<endl;break;case 3:bt.PostOrder(root);cout<<endl;break;case 4:bt.LeverOrder(root);cout<<endl;break;case 5:cout<<"树的深度为:"<<bt.depth(root)<<endl;break;case 6:bt.empty();bt.leafnum(root);cout<<"叶子结点个数为:"<<bt.printnum()<<endl;break;case 7:bt.empty();bt.sbnodenum(root);cout<<"单分支结点个数为:"<<bt.printnum()<<endl;break;case 8:bt.empty();bt.exchangetree(root);cout<<"左右子树交换后的结果:";bt.PreOrder(root);cout<<endl;break;case 0:exit(0);}}}。
(完整版)C++二叉树基本操作实验报告
一、实验目的选择二叉链式存储结构作为二叉树的存储结构,设计一个程序实现二叉树的基本操作(包括建立、输出、前序遍历、中序遍历、后序遍历、求树高、统计叶子总数等)二、实验开发环境Windows 8.1 中文版Microsoft Visual Studio 6.0三、实验内容程序的菜单功能项如下:1------建立一棵二叉树2------前序遍历递归算法3------前序遍历非递归算法4------中序遍历递归算法5------中序遍历非递归算法6------后序遍历递归算法7------后序遍历非递归算法8------求树高9------求叶子总数10-----输出二叉树11-----退出四、实验分析1、建立一棵二叉树2、输入二叉树各节点数据cout<<"请按正确顺序输入二叉树的数据:";cin.getline(t,1000); //先把输入的数据输入到一个t数组3、递归前序遍历void BL1(ECS_data *t){if(NULL!=t){cout<<t->data<<",";BL1(t->l);BL1(t->r);}}4、非递归前序遍历void preOrder2(ECS_data *t){stack<ECS_data*> s;ECS_data *p=t;while(p!=NULL||!s.empty()){while(p!=NULL){cout<<p->data<<" ";s.push(p);p=p->l;}if(!s.empty()){p=s.top();s.pop();p=p->r;}}}5、递归中序遍历void BL2(ECS_data *t){if(NULL!=t){BL2(t->l);cout<<t->data<<",";BL2(t->r);}}6、非递归中序遍历void inOrder2(ECS_data *t) //非递归中序遍历{stack<ECS_data*> s;ECS_data *p=t;while(p!=NULL||!s.empty()){while(p!=NULL){s.push(p);p=p->l;}if(!s.empty()){p=s.top();cout<<p->data<<" ";s.pop();p=p->r;}}}7、递归后序遍历void BL3(ECS_data *t){if(NULL!=t){BL3(t->l);BL3(t->r);cout<<t->data<<",";}}8、非递归后序遍历void postOrder3(ECS_data *t){stack<ECS_data*> s;ECS_data *cur; //当前结点ECS_data *pre=NULL; //前一次访问的结点s.push(t);while(!s.empty()){cur=s.top();if((cur->l==NULL&&cur->r==NULL)||(pre!=NULL&&(pre==cur->l||pre==cur->r))){cout<<cur->data<<" "; //如果当前结点没有孩子结点或者孩子节点都已被访问过s.pop();pre=cur;}else{if(cur->r!=NULL)s.push(cur->r);if(cur->l!=NULL)s.push(cur->l);}}}9、求树高int Height (ECS_data *t){if(t==NULL) return 0;else{int m = Height ( t->l );int n = Height(t->r);return (m > n) ? (m+1) : (n+1);}}10、求叶子总数int CountLeaf(ECS_data *t){static int LeafNum=0;//叶子初始数目为0,使用静态变量if(t)//树非空{if(t->l==NULL&&t->r==NULL)//为叶子结点LeafNum++;//叶子数目加1else//不为叶子结点{CountLeaf(t->l);//递归统计左子树叶子数目CountLeaf(t->r);//递归统计右子树叶子数目}}return LeafNum;}五、运行结果附:完整程序源代码://二叉树链式存储的实现#include<iostream>#include<cstring>#include <stack>using namespace std;struct ECS_data //先定义好一个数据的结构{char data;ECS_data *l;ECS_data *r;};class ECS{private://int level; //树高int n; //表示有多少个节点数int n1; //表示的是数组的总长度值,(包括#),因为后面要进行删除判断ECS_data *temp[1000];public:ECS_data *root;ECS() //初始化{ECS_data *p;char t[1000];int i;int front=0,rear=1; //front表示有多少个节点,rear表示当前插入的点的父母cout<<"请按正确顺序输入二叉树的数据:";cin.getline(t,1000); //先把输入的数据输入到一个t数组//cout<<t<<" "<<endl;int n1=strlen(t); //测量数据的长度n=0;for(i=0;i<n1;i++){if(t[i]!='#'){p=NULL;if(t[i]!=',') //满足条件并开辟内存{n++;p=new ECS_data;p->data=t[i];p->l=NULL;p->r=NULL;}front++;temp[front]=p;if(1 == front){root=p;}else{if((p!=NULL)&&(0==front%2)){temp[rear]->l=p;//刚开始把这里写成了==}if((p!=NULL)&&(1==front%2)){temp[rear]->r=p;}if(1==front%2)rear++; //就当前的数据找这个数据的父母}}}}~ECS() //释放内存{int i;for(i=1;i<=n;i++)if(temp[i]!=NULL)delete temp[i];}void JS() //记录节点的个数{int s;s=n;cout<<"该二叉树的节点数为:"<<s<<endl;}void BL1(ECS_data *t)//递归前序遍历{if(NULL!=t){cout<<t->data<<",";BL1(t->l);BL1(t->r);}}void preOrder2(ECS_data *t) //非递归前序遍历{stack<ECS_data*> s;ECS_data *p=t;while(p!=NULL||!s.empty()){while(p!=NULL){cout<<p->data<<" ";s.push(p);p=p->l;}if(!s.empty()){p=s.top();s.pop();p=p->r;}}}void BL2(ECS_data *t)//递归中序遍历{if(NULL!=t){BL2(t->l);cout<<t->data<<",";BL2(t->r);}}void inOrder2(ECS_data *t) //非递归中序遍历{stack<ECS_data*> s;ECS_data *p=t;while(p!=NULL||!s.empty()){while(p!=NULL){s.push(p);p=p->l;}if(!s.empty()){p=s.top();cout<<p->data<<" ";s.pop();p=p->r;}}}void BL3(ECS_data *t)//递归后序遍历{if(NULL!=t){BL3(t->l);BL3(t->r);cout<<t->data<<",";}}void postOrder3(ECS_data *t) //非递归后序遍历{stack<ECS_data*> s;ECS_data *cur; //当前结点ECS_data *pre=NULL; //前一次访问的结点s.push(t);while(!s.empty()){cur=s.top();if((cur->l==NULL&&cur->r==NULL)||(pre!=NULL&&(pre==cur->l||pre==cur->r))){cout<<cur->data<<" "; //如果当前结点没有孩子结点或者孩子节点都已被访问过s.pop();pre=cur;}else{if(cur->r!=NULL)s.push(cur->r);if(cur->l!=NULL)s.push(cur->l);}}}int Height (ECS_data *t) //求树高{if(t==NULL) return 0;else{int m = Height ( t->l );int n = Height(t->r);return (m > n) ? (m+1) : (n+1);}}int CountLeaf(ECS_data *t) //求叶子总数{static int LeafNum=0;//叶子初始数目为0,使用静态变量if(t)//树非空{if(t->l==NULL&&t->r==NULL)//为叶子结点LeafNum++;//叶子数目加1else//不为叶子结点{CountLeaf(t->l);//递归统计左子树叶子数目CountLeaf(t->r);//递归统计右子树叶子数目}}return LeafNum;}};int main(){ECS a;a.JS();cout<<"递归前序遍历:";a.BL1(a.root);cout<<endl;cout<<"非递归前序遍历:";a.preOrder2(a.root);cout<<endl;cout<<"递归中序遍历:";a.BL2(a.root);cout<<endl;cout<<"非递归中序遍历:";a.inOrder2(a.root);cout<<endl;cout<<"递归后序遍历:";a.BL3(a.root);cout<<endl;cout<<"非递归后序遍历:";a.postOrder3(a.root);cout<<endl;cout<<"树高为:"<<a.Height(a.root)<<endl;cout<<"叶子总数为:"<<a.CountLeaf(a.root)<<endl;return 0;}。
实验五 二叉树的基本操作
实验五还原二叉树实验目的:1.熟练掌握二叉树存储结构。
2.熟练掌握二叉树的遍历及应用。
实验内容:给定一棵二叉树的先序遍历序列和中序遍历序列,要求计算该二叉树的高度。
实验要求:1.输入说明:输入第1行给出正整数N(N≤50),为树中结点总数。
下面2行先后给出先序和中序遍历序列,均是长度为N的不包含重复英文字母(区别大小写)的字符串。
2.输出说明:输出为一个整数,即该二叉树的高度。
测试用例:实验分析:1.问题分析本题需要解决两个子问题。
通过输入给定的先序遍历和中序遍历两个序列构建对应二叉树。
由于我们知道先序遍历序列的第1个结点必然是根结点,可以在中序遍历序列中找到这个根结点的位置,于是就知道在中序遍历序列中,根结点左边的所有结点一定属于左子树,右边的所有结点一定属于右子树。
根据这个判断,可以从中序遍历序列中知道左、右子树分别有L和R个结点,它们必然对应存储在先序遍历序列中第2~(L+1)个结点以及最后的R个结点。
于是可以对左、右子树递归地解决这个问题,直到生成整个二叉树。
求二叉树的高度。
如果已经知道左、右子树的高度,那么树的高度就是左、右子树中比较高的那个高度加1。
这是一个可以用二叉树后序遍历解决的问题,在遍历过程中,我们将“访问结点”定义为“求左、右子树高度的较大值并加1”。
2.实现要点树形结构用教材中介绍的链表结构存储,结点结构体存储该结点的字符以及左右子树的指针。
在构建二叉树和求二叉树高度的过程中,须注意递归终止的条件。
实验参考代码:#include<stdio.h>#include<stdlib.h>#define MAXN 50typedef struct TreeNode *BinTree;struct TreeNode{char Data;BinTree Left;BinTree Right;};BinTree CreateBinTree( char *Pre, char *In, int Len ) { /* 根据先序遍历序列和中序遍历序列构造二叉树*/ BinTree T;int i;if ( !Len ) return NULL; /* 递归终止*//* 建立当前根结点*/T = (BinTree)malloc(sizeof(struct TreeNode));T->Data = Pre[0];for (i=0; i<Len; i++) /* 在中序里找根结点*/if (Pre[0]==In[i]) break;/* 递归生成左右子树*/T->Left = CreateBinTree(Pre+1, In, i);T->Right = CreateBinTree(Pre+i+1, In+i+1, Len-i-1);return T;}int Height( BinTree T ){ /* 求树的高度*/int THeight, LHeight, RHeight;if( !T ) /* 递归终止条件*/THeight=0;else { /* 后序遍历*/LHeight = Height(T->Left);RHeight = Height(T->Right);THeight = (LHeight>RHeight)? LHeight : RHeight;THeight++; /* 树高为左右树高较大者加1 */}return THeight;}int main(){int N;char Pre[MAXN+1], In[MAXN+1];BinTree T = NULL;scanf("%d", &N);scanf("%s\n%s", Pre, In);T = CreateBinTree(Pre, In, N);printf("%d\n", Height(T));return 0;}实验思考题:1.如果题目改为给定后序和中序遍历序列,该如何修改程序?2.如果题目输入的序列不保证正确,如何修改程序识别不匹配的错误?。
二叉树的操作实验报告
二叉树的操作实验报告二叉树的操作实验报告引言二叉树是计算机科学中常用的数据结构,它具有良好的搜索性能和灵活的插入和删除操作。
本实验旨在通过实际操作,深入理解二叉树的基本操作和特性。
1. 二叉树的定义和基本概念二叉树是一种特殊的树状结构,每个节点最多有两个子节点,分别称为左子节点和右子节点。
二叉树的节点由数据和指向左右子节点的指针组成。
根据节点的位置,可以将二叉树分为左子树、右子树和根节点。
2. 二叉树的遍历二叉树的遍历是指按照一定的顺序访问二叉树中的所有节点。
常用的遍历方式有前序遍历、中序遍历和后序遍历。
前序遍历先访问根节点,然后按照左子树、右子树的顺序遍历;中序遍历先访问左子树,然后根节点,最后右子树;后序遍历先访问左子树,然后右子树,最后根节点。
3. 二叉树的插入操作插入操作是将一个新节点插入到二叉树中的特定位置。
插入操作需要考虑节点的大小关系,小于当前节点则插入到左子树,大于当前节点则插入到右子树。
插入操作可以保持二叉树的有序性。
4. 二叉树的删除操作删除操作是将指定节点从二叉树中删除。
删除操作需要考虑被删除节点的子节点情况,如果被删除节点没有子节点,则直接删除;如果有一个子节点,则将子节点替代被删除节点的位置;如果有两个子节点,则选择被删除节点的后继节点或前驱节点替代被删除节点。
5. 二叉树的查找操作查找操作是在二叉树中搜索指定的节点。
二叉树的查找操作可以使用递归或迭代的方式实现。
递归方式会自动遍历整个二叉树,直到找到目标节点或遍历完整个树。
迭代方式则需要手动比较节点的值,并根据大小关系选择左子树或右子树进行进一步查找。
6. 二叉树的平衡性二叉树的平衡性是指左子树和右子树的高度差不超过1。
平衡二叉树可以提高搜索效率,避免出现极端情况下的性能下降。
常见的平衡二叉树有AVL树和红黑树。
7. 二叉树应用场景二叉树在计算机科学中有广泛的应用场景。
例如,文件系统的目录结构可以使用二叉树来表示;数据库中的索引结构也可以使用二叉树来实现。
二叉树的基本操作实验报告
二叉树的基本操作实验报告学号姓名实验日期 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,<root,x1>?H,且存在D1上的关系H1 ?H;若Dr?Φ,则Dr中存在惟一的元素xr,<root,xr>?H,且存在上的关系Hr ?H;H={<root,x1>,<root,xr>,H1,Hr};// (4)(D1,{H1})是一棵符合本定义的二叉树,称为根的左子树;(Dr,{Hr})是一棵符合本定义的二叉树,称为根的右子树。
//基本操作:CreateBiTree( &T, definition ) // 初始条件:definition给出二叉树T的定义。
// 操作结果:按definiton构造二叉树T。
BiTreeDepth( T )// 初始条件:二叉树T存在。
// 操作结果:返回T的深度。
PreOrderTraverse( T, visit() ) // 初始条件:二叉树T存在,Visit是对结点操作的应用函数。
实验五 数据结构 二叉树基本操作实验报告(汽院)
班级:
教师批阅处:
一、实验名称
二叉树基本操作的编程实现
二、实验目的
二叉树基本操作的编程实现,掌握二叉树的建立、遍历、插入、删除等基本操作的编程实现,存储结构主要采用链接结构。
三、实验内容
本次实验的内容有三种模式,我选择了第三种模式:用c进行程序的改进和提高,把下面的程序源码进行输入和改写,调试,直到成功。
1、补充三种递归遍历的方法
先根遍历:若二叉树不为空,先访问根节点,然后访问根节点的左子树,最后访问根节点的右子树。
中根遍历:若二叉树不为空,先访问根节点的左子树,然后访问根节点,最后访问根节点的右子树。
后跟遍历:若二叉树不为空,先访问根节点的左子树,然后访问根节点的右子树,最后访问根节点。
三种遍历的效果截图如下:
{
if(pnow!=NULL)
{
if (top<Maxsize-1)
{
top++;
stack[top].link=pnow;
stack[top].flag=1;
pnow=pnow->lchild;
}
else
{ return overflow; }
}
else
{
pnow=stack[top].link;
cout<<",";
else
cout<<")";
pnow=NULL;
}
}
}
cout<<endl;
return success;
}
3、补充层次遍历的方法
若二叉树不为空,从根节点开始从上至下逐层访问,同一层中从左到右逐个结点访问。效果截图如下:
数据结构与算法实验——二叉树基本操作
二叉树基本操作实验报告实验名称二叉树基本操作实验目的1.熟悉二叉树结点的结构和二叉树的基本操作;2.掌握二叉树每种操作的具体实现;3.学会利用递归方法编写对二叉树这种递归数据结构进行处理的算法;4.在二叉树基本操作的基础上掌握对二叉树的一些其它操作的具体实现方法;5.掌握构造哈夫曼树以及哈夫曼编码的方法。
实验内容编制一个演示二叉树创建、遍历、计算等操作的程序。
问题描述用数据结构相关知识,实现二叉树的定义和操作。
该程序包括二叉树结构类型以及对二叉树操作的具体的函数定义(包括:初始化二叉树、清空二叉树、检查二叉树是否为空、遍历二叉树(先序、后序、中序、层次)、求二叉树的深度、求二叉树所有节点数)。
问题分析该实验是基于C语言和数据结构知识基础的对二叉树的基本操作的检验,无需设计复杂的算法,程序语句也相对简单。
因此,我直接按要求定义了对二叉树操作的具体函数,并于主函数中实现对应的功能调用,其中,功能选择靠switch语句实现。
实验步骤1.需求分析本演示程序用VC++编写,完成二叉树的生成、遍历、计算等基本操作。
①输入的形式和输入值的范围:以字符(其中‘#’表示虚节点)的形式输入,以创建二叉树;在输入二叉树节点前,必须先确定该序列能正确创建二叉树。
②输出的形式:在所有三种操作中都显示操作是否正确以及操作后二叉树的内容。
③程序所能达到的功能:完成二叉树的生成、遍历(包括先序、后序、中序、层次四种方式)、计算等基本操作。
④测试数据:创建操作中依次输入a,b,d,#,g,#,#,#,c,e,#,#,f,#,#生成一个二叉树。
2.概要设计1)为了实现上述程序功能,需要定义二叉树的抽象数据类型:ADT BitTree {数据对象:由一个根节点和两个互不相交的左右子树构成数据关系:结点具有相同的数据类型及层次结构基本操作:Void BinTreeInit(BitTree *T)初始条件:无操作结果:初始化一棵二叉树Void BinTreeCreat(BitTree *T)初始条件:二叉树T已存在操作结果:按先序次序创建一棵二叉树2)本程序包含7个函数:①主函数main() ②初始化二叉树函数BinTreeInit() ③建立一棵二叉树函数BinTreeCreat() ④先序遍历函数PreOrderTraverse() ⑤中序遍历函数InOrderTraverse()⑥后序遍历函数PostOrderTraverse()⑦层次遍历函数LevelOrderTraverse()⑧求二叉树深度函数Countlevel()⑨检验空树函数BinTreeEmpty()⑩求节点数函数 Countnode()函数说明#include<stdio.h>#include<stdlib.h>typedef char Datatype;typedef struct NodeType{Datatype data;struct NodeType *lchild;struct NodeType *rchild;}BiTNode;typedef BiTNode * BinTree;//初始化二叉树。
数据结构:二叉搜索树的基本操作
数据结构:二叉搜索树的基本操作前言碎语这因为学习树结构里面的最基本操作了,但是作为小白入门,哪怕是最基础的也会感觉困难重重,所以,最稳的方法:乐观好心态,咱一步一步,一点一点来。
几点说明树的结构在定义的时候,用的是嵌套结构,即树的左右子树也都是树。
在建立树的时候,每一次只申请一块栈空间,所以需要for循环来调用;BST、BST -> Left、BST -> Right表示的都是地址,所以Insert函数那里,最后返回的是地址。
原题描述二叉搜索树的操作集 (30 point(s))本题要求实现给定二叉搜索树的5种常用操作。
函数接口定义:BinTree Insert( BinTree BST, ElementType X );BinTree Delete( BinTree BST, ElementType X );Position Find( BinTree BST, ElementType X );Position FindMin( BinTree BST );Position FindMax( BinTree BST );其中BinTree结构定义如下:typedef struct TNode *Position;typedef Position BinTree;struct TNode{ElementType Data;BinTree Left;BinTree Right;};函数Insert将X插入二叉搜索树BST并返回结果树的根结点指针;函数Delete将X从二叉搜索树BST中删除,并返回结果树的根结点指针;如果X不在树中,则打印一行Not Found并返回原树的根结点指针;函数Find在二叉搜索树BST中找到X,返回该结点的指针;如果找不到则返回空指针;函数FindMin返回二叉搜索树BST中最小元结点的指针;函数FindMax返回二叉搜索树BST中最大元结点的指针。
裁判测试程序样例:#include <stdio.h>#include <stdlib.h>typedef int ElementType;typedef struct TNode *Position;typedef Position BinTree;struct TNode{ElementType Data;BinTree Left;BinTree Right;};void PreorderTraversal( BinTree BT ); /* 先序遍历,由裁判实现,细节不表 */void InorderTraversal( BinTree BT ); /* 中序遍历,由裁判实现,细节不表 */BinTree Insert( BinTree BST, ElementType X );BinTree Delete( BinTree BST, ElementType X );Position Find( BinTree BST, ElementType X );Position FindMin( BinTree BST );Position FindMax( BinTree BST );int main(){BinTree BST, MinP, MaxP, Tmp;ElementType X;int N, i;BST = NULL;scanf("%d", &N);for ( i=0; i<N; i ) {scanf("%d", &X);BST = Insert(BST, X);}printf("Preorder:"); PreorderTraversal(BST); printf("\n");MinP = FindMin(BST);MaxP = FindMax(BST);scanf("%d", &N);for( i=0; i<N; i ) {scanf("%d", &X);Tmp = Find(BST, X);if (Tmp == NULL) printf("%d is not found\n", X);else {printf("%d is found\n", Tmp->Data);if (Tmp==MinP) printf("%d is the smallest key\n", Tmp->Data);if (Tmp==MaxP) printf("%d is the largest key\n", Tmp->Data);}}scanf("%d", &N);for( i=0; i<N; i ) {scanf("%d", &X);BST = Delete(BST, X);}printf("Inorder:"); InorderTraversal(BST); printf("\n");return 0;}/* 你的代码将被嵌在这里 */输入样例:105 86 2 4 1 0 10 9 756 3 10 0 555 7 0 10 3输出样例:Preorder: 5 2 1 0 4 8 6 7 10 96 is found3 is not found10 is found10 is the largest key0 is found0 is the smallest key5 is foundNot FoundInorder: 1 2 4 6 8 9具体实现如下#include <cstdio>#include <cstdlib>//BinTree 结构定义typedef int ElementType;typedef struct TNode *Position;typedef Position BinTree;struct TNode {ElementType Data;BinTree Left;BinTree Right;};//实现前序、中序、后序遍历//这里的遍历就是把printvoid PreorderTraversal(BinTree BT);void InorderTraversal(BinTree BT);void PostorderTraversal(BinTree BT);//层序遍历//需要用到队列结构//void LevelorderTraversal(BinTree BT);//实现插入、删除、查找结点,最大最小结点的位置BinTree Insert(BinTree BST, ElementType X); BinTree Delete(BinTree BST, ElementType X); Position Find(BinTree BST, ElementType X); Position FindMin(BinTree BST);Position FindMax(BinTree BST);int main()BinTree BST, MinP, MaxP, Tmp;ElementType X;int N, i;BST = NULL;scanf("%d", &N);for ( i=0; i<N; i ) {scanf("%d", &X);BST = Insert(BST, X);}printf("Preorder:"); PreorderTraversal(BST); printf("\n");MinP = FindMin(BST);MaxP = FindMax(BST);scanf("%d", &N);for( i=0; i<N; i ) {scanf("%d", &X);Tmp = Find(BST, X);if (Tmp == NULL) printf("%d is not found\n", X);else {printf("%d is found\n", Tmp->Data);if (Tmp==MinP) printf("%d is the smallest key\n", Tmp->Data);if (Tmp==MaxP) printf("%d is the largest key\n", Tmp->Data);}}scanf("%d", &N);for( i=0; i<N; i ) {scanf("%d", &X);BST = Delete(BST, X);printf("Inorder:"); InorderTraversal(BST); printf("\n");return 0;}//中序遍历void InorderTraversal(BinTree BT){if (BT) {InorderTraversal(BT -> Left);printf("%d ", BT -> Data);InorderTraversal(BT -> Right);}}//前序遍历void PreorderTraversal(BinTree BT){if (BT) {printf("%d ", BT -> Data);PreorderTraversal(BT -> Left); PreorderTraversal(BT -> Right);}}//后序遍历void PostorderTraversal(BinTree BT){if (BT) {PostorderTraversal(BT -> Left); PostorderTraversal(BT -> Right);printf("%d ", BT -> Data);}}//二叉搜索树的插入BinTree Insert(BinTree BST, ElementType X){//如果是空树,申请一个结点空间if (!BST) {BST = (BinTree)malloc(sizeof(struct TNode));//然后把数据存进去(即根结点,和链表的头结点有些不同)BST -> Data = X;BST -> Left = BST -> Right = NULL;}else {if (X < BST -> Data)//因为返回的是结点的地址BST -> Left = Insert(BST -> Left, X);else if (X > BST -> Data)BST -> Right = Insert(BST -> Right, X);}return BST; //正好相等时直接返回}BinTree Delete(BinTree BST, ElementType X){Position Temp; //临时结点if (!BST)printf("Not Found\n");else {if (X < BST -> Data)BST -> Left = Delete(BST -> Left, X);else if (X > BST -> Data)BST -> Right = Delete(BST -> Right, X);else {//这里需要分该结点有左右孩子//就找左子树最大或者右子树最小if (BST -> Left && BST -> Right) {Temp = FindMax(BST -> Left);BST -> Data = Temp -> Data;//重新赋值,“相当于”结点的删除//然后把这个结点删掉就好BST -> Left = Delete(BST -> Left, BST -> Data); }else {Temp = BST;if (!BST -> Left)BST = BST -> Right;elseBST = BST -> Left;free(Temp);}}}return BST;}//直接查找,while循环Position Find(BinTree BST, ElementType X) {while (BST) {if (X < BST -> Data)BST = Find(BST -> Left, X);else if (X > BST -> Data)BST = Find(BST -> Right, X);elsereturn BST;}return NULL;}//最小一定在最左的孩子上Position FindMin(BinTree BST){if (!BST)return NULL;else if (!BST -> Left)return BST;elsereturn FindMin(BST -> Left);}Position FindMax(BinTree BST){if (!BST)return NULL;else if (!BST -> Right)return BST;elsereturn FindMax(BST -> Right); }来源:。
西电软件工程大作业——二叉排序树
1.题目二叉排序树2.功能描述1.构造二叉查找树(1)从文本文件中读入文本内容,能够分离出单词,过滤掉阿拉伯数字和标点符号,并将英文字母的大写形式全部转换成小写形式。
(2)按照英文字母表的顺序构造英文单词的二叉查找树。
当两个英文单词的首字母相同时,按第二个字母进行排序,依次类推。
(3)当待插入的单词已在二叉查找树中,则将该单词的出现次数增1。
2.遍历二叉查找树(1)搜索:输入一个待检索单词,在二叉查找树中进行查找,如果能找到该单词,则输出该单词及其出现次数;(2)实现二叉查找树的中序遍历,并将遍历结果输出到屏幕上,包括单词和单词出现的位置。
3.删除结点:给定一个停用词列表(停用词是指对搜索没有作用的词,如:of,and,a,an,the等等),将二叉查找树中的属于停用词表中的单词依次删除。
4.可以显示菜单,在菜单中可以进行如下四项操作(但并不局限这些操作):(1)读入文本内容,包含若干英文单词、标点符号以及阿拉伯数字,用于构建二叉查找树。
(2)输入停用词,每个停用词占一行。
对于每个停用词,都需要删除二叉查找树中的相应结点,即:每输入一个停用词,执行一次删除结点的操作。
(3)中序遍历二叉查找树,遍历结果中的每个单词占一行,先输出该单词,然后输出一个空格,再输出该单词出现的次数。
(4)输入查询词。
对每个查询词,都需要在二叉查找树中的搜索相应结点,如果找到,则输出该单词及其出现次数;如果未找到,则输出相应的信息。
每个查询词的查询结果占一行,先输出该单词,然后输出一个空格,再输出该单词出现的次数。
3.流程图4.程序源代码和注释#include<stdio.h> //头文件#include<stdlib.h>#include<string.h>typedef char keytype;typedef struct node //定义结构体类型{keytype *key; //数据域int weight; //权重struct node *lchild,*rchild; //左右孩子指针}bstnode;bstnode*INSERTBST(bstnode*t,bstnode*s)//二叉排序树的(非递归)插入返回根节点已知(根节点,插入节点){bstnode*f,*p;p=t; //p指向根节点while(p!=NULL) //遍历树,直至找到相同单词或p为NULL {f=p; //f指向p的双亲(当未找到相同单词)if(strcmp(s->key,p->key)==0) //单词相同频次加1{p->weight=p->weight+1;return t;}if(strcmp(s->key,p->key)<0) p=p->lchild; //查找左子树else p=p->rchild; //查找右子树}if(t==NULL) return s; //原树为空,返回s为根节点if(strcmp(s->key,f->key)<0) f->lchild=s; //s插入为f的左孩子else f->rchild=s; //s插入为f的右孩子return t;}bstnode*CREATEBST() //读取文件并建立二叉排序树返回根节点{bstnode *t,*s;long int i,j=0;char ch,string[2000000]; //声明总单词字符串长度FILE*fp;fp=fopen("D:/工具/创建的文件/0.txt","r"); //读取文件do //去除非字母字符并将大写字母转换为小写字母{i=20*j; //使每个单词首字母间隔20while(1){ch=fgetc(fp); //逐个读取字符if(ch>='a'&&ch<='z') //小写字母直接插入{string[i]=ch;i++;}else if(ch>='A'&&ch<='Z') //大写字母转化为小写字母后插入{string[i]=ch+32;i++;}else break; //如果读入非字母字符,单词输入结束跳出循环}string[i]='\0'; //在每个单词后加'\0'if(string[j*20]!='\0') j++; //没有单词输入保留原位不变}while(ch!=EOF); //读取结束跳出循环keytype *key=string; //key指向string[0]t=NULL; //令t为NULLwhile(*key!='\0') //建立二叉树插入所有单词{s=(bstnode*)malloc(sizeof(bstnode)); //建立新节点s->lchild=s->rchild=NULL; //另新节点左右孩子为空s->key=key; //新节点赋值s->weight=1; //初始权重为1t=INSERTBST(t,s); //把新节点插入到树中key=key+20; //令key指向下一个单词首字母}return t; //返回根节点}bstnode*Search(bstnode*t,char*word)//二叉排序树的查找返回所查找单词节点已知(根节点,单词数组){bstnode*p;p=t; //令p指向根节点while(p!=NULL) //遍历整个树{if(strcmp(word,p->key)==0) break; //查找正确,跳出循环else if(strcmp(word,p->key)<0) p=p->lchild;//小于根节点令P指向其左孩子else p=p->rchild; //大于根节点令P指向其右孩子}return p; //返回查找到的地址}void PutSearch(bstnode*t,char*word)//输出查找的单词和频次已知(根节点,单词数组){bstnode*p;p=Search(t,word); //查找所需单词节点if(p!=NULL) printf("%s %d\n",p->key,p->weight);//查找成功输出单词和频次else printf("There is not the word.\n"); //查找不成功输出未查到}void inorder(bstnode*t) //中序遍历输出已知(根节点){if(t!=NULL) //根节点不为NULL进行操作{inorder(t->lchild); //中序遍历左子树printf("%s %d %p\n",t->key,t->weight,t->key);//输出节点的单词频次和地址inorder(t->rchild); //中序遍历右子树}}bstnode*FindP(bstnode*t,bstnode*s) //遍历查找任意节点的双亲节点返回这个节点的双亲节点已知(根节点,查找节点){bstnode*m,*temp=NULL; //temp为标识符(判断是否查找成功)m=t; //m指向根节点if(t==NULL) return NULL; //根节点位NULL 返回NULLif(t==s) return NULL; //查找节点为根节点返回NULLif(m->lchild==s||m->rchild==s) return m; //子节点为查找值返回地址else{if(temp=FindP(m->lchild,s)) return temp;//遍历左子树,未找到返回NULLif(temp=FindP(m->rchild,s)) return temp;//遍历右子树未找到返回NULL}}int LorR(bstnode*p,bstnode*s) //判断子节点为左孩子还是右孩子{if(p->lchild==s) return 1; //左返回1else return 2; //右返回2}bstnode*Max(bstnode*t)//查找二叉排序树中的最大节点(递归)返回最大节点已知(根节点){if(t->rchild!=NULL) Max(t->rchild); //右子树不为NULL,遍历右子树else return t; //返回最大节点}bstnode*Deletenode(bstnode*t,bstnode*s)//删除停用词节点(遍历)返回根节点已知(根节点,删除节点){int d;bstnode*p,*m;if(s==NULL); //删除节点在二叉排序树中不存在,直接返回根节点else{p=FindP(t,s); //查找停用词节点的双亲节点if(s->lchild==NULL&&s->rchild==NULL) //s为叶子节点{if(p==NULL) free(s); //s为根节点,直接释放else{d=LorR(p,s); //判断S为P的左孩子还是右孩子if(d==1) //左孩子{p->lchild=NULL; //将其双亲节点左孩子指针置空free(s); //释放S节点}if(d==2) //右孩子{p->rchild=NULL; //将其双亲节点孩子指针置空free(s); //释放S节点}}}else if(s->lchild!=NULL&&s->rchild==NULL) //s仅有左子树{if(p==NULL) //s为根结点{free(s);return s->lchild; //返回s的左孩子节点}else{d=LorR(p,s); //判断S为P的左孩子还是右孩子if(d==1) //左孩子{p->lchild=s->lchild; //将S的左孩子成为p的左孩子free(s); //释放S节点}if(d==2) //右孩子{p->rchild=s->lchild; //将S的左孩子成为p的右孩子free(s); //释放S节点}}}else if(s->lchild==NULL&&s->rchild!=NULL) //s仅有右子树{if(p==NULL) //s为根结点{free(s);return s->rchild; //返回s的右孩子节点}else{d=LorR(p,s); //判断S为P的左孩子还是右孩子if(d==1) //左孩子{p->lchild=s->rchild; //将S的右孩子成为p的左孩子free(s); //释放S节点}if(d==2) //右孩子{p->rchild=s->rchild; //将S的右孩子成为p的右孩子free(s); //释放S节点}}}else if(s->lchild!=NULL&&s->rchild!=NULL) //s既有左子树又有子树{m=Max(s->lchild); //中序遍历查找s左子树最大节点s->key=m->key; //以最大节点代替删除节点s->weight=m->weight;Deletenode(s,m); //删除最大节点}}return t;}int main(){char e[]={"end"},word[20]; //end作为中止符char x; //x为操作符bstnode*t,*s;printf("-------------操作选项-----------\n"); //建立菜单printf("1:读入文本建立二叉排序树\n");printf("2:输入停用词删除节点\n");printf("3:二叉树中序遍历输出\n");printf("4:查询单词并输出频次\n");printf("5:退出程序\n");printf("--------------------------------\n");while(1) //不断执行菜单内容直至退出程序{printf("输入数字选择执行操作:");scanf("%c",&x); //输入操作种类fflush(stdin); //清除输入缓冲流中的回车符(scanf所产生)if(x=='5') break; //程序退出switch(x) //判断操作类型{case '1':t=CREATEBST(); break;//读入文本建立二叉排序树case '2':while(1) //连续删除停用词,直到输入end{printf("输入停用词(end为终止符):");gets(word);if(strcmp(word,e)==0) break;//终止删除停用词,返回菜单else{s=Search(t,word); //查找停用词地址t=Deletenode(t,s); //删除停用词}} break;case '3':inorder(t); break; //中序遍历输出case '4':while(1) //连续查询,直至输入end{printf("输入查询单词(end为终止符):");gets(word);if(strcmp(word,e)==0) break; //终止查询,返回菜单else PutSearch(t,word); //查询单词并输出频次} break;default:printf("输入错误请重输\n"); break; //提示输入的是非法操作符}}return 0;}5.数据检测1.读入的文件2.检测步骤及结果读入文件---中序遍历输出---查找(for,the)---停用(for,the)---查找(for,the)---中序遍历输出---结束程序6.心得体会在编程过程,学会了由文本文件读取文本内容,并在其中删除非字母字符和转换大小写。
二叉树的基本操作与实现实验报告
二叉树的基本操作与实现实验报告二叉树是一种重要的数据结构,在计算机科学领域中被广泛应用。
本实验将介绍二叉树的基本操作与实现,并给出相应的实验报告。
一、引言二叉树是一种特殊的树状结构,每个节点至多有两个子节点。
二叉树有许多重要的特性,如平衡二叉树、二叉树等,应用广泛。
在本实验中,我们将介绍二叉树的基本操作和实现。
二、实验目的1.掌握二叉树的基本概念和特性;2.熟悉二叉树的基本操作,包括创建、插入、删除、遍历等;3.学会使用编程语言实现二叉树的基本操作。
三、实验内容本实验主要包括以下内容:1.二叉树的定义和基本概念;2.二叉树的基本操作,包括创建、插入、删除、遍历等;3.使用编程语言实现二叉树的基本操作;4.测试和验证二叉树的基本操作的正确性。
四、实验步骤1.二叉树的定义和基本概念二叉树是一种树状结构,每个节点至多有两个子节点。
二叉树的每个节点包含一个数据项和指向左子树和右子树的指针。
二叉树的特性有很多,如完全二叉树、平衡二叉树、二叉树等。
2.二叉树的基本操作(1)创建二叉树:可以通过手动输入节点数据来创建二叉树,也可以通过读取文件中的数据来创建二叉树。
(2)插入节点:在指定位置插入一个新节点。
(3)删除节点:删除指定位置的节点。
(4)遍历二叉树:有前序遍历、中序遍历和后序遍历三种遍历方式。
3.使用编程语言实现二叉树的基本操作实现二叉树的基本操作可以使用编程语言来完成。
我们可以定义一个二叉树的结构体,包含节点数据和指向左右子树的指针。
然后根据具体的需求,实现相应的操作函数。
4.测试和验证二叉树的基本操作的正确性在完成二叉树的基本操作后,我们可以编写测试代码来验证操作的正确性。
通过创建二叉树,并进行插入、删除和遍历操作,观察输出结果是否符合预期。
五、实验结果与分析在完成二叉树的基本操作后,我们可以进行测试和验证。
通过输出二叉树的遍历结果,比对预期结果来判断操作是否正确。
同时,我们还可以观察二叉树的结构和特性,如是否满足平衡二叉树或二叉树的条件。
二叉树的基本操作实验报告
二叉树的基本操作实验报告二叉树的基本操作实验报告引言:二叉树是一种常见的数据结构,它由节点组成,每个节点最多有两个子节点。
二叉树的基本操作包括创建、遍历、插入和删除等。
本实验旨在通过实践来深入了解二叉树的基本操作,并通过实验结果验证其正确性和有效性。
一、创建二叉树创建二叉树是二叉树操作中的第一步。
在本实验中,我们使用了递归算法来创建二叉树。
递归算法是一种重要的算法思想,通过将问题划分为更小的子问题来解决复杂的问题。
在创建二叉树时,我们首先创建根节点,然后递归地创建左子树和右子树。
二、遍历二叉树遍历二叉树是对二叉树中的每个节点进行访问的过程。
常见的遍历方式有前序遍历、中序遍历和后序遍历。
前序遍历先访问根节点,然后递归遍历左子树和右子树;中序遍历先递归遍历左子树,然后访问根节点,最后递归遍历右子树;后序遍历先递归遍历左子树和右子树,最后访问根节点。
三、插入节点插入节点是向二叉树中添加新节点的操作。
插入节点的过程需要遵循二叉树的特性,即左子节点的值小于父节点的值,右子节点的值大于父节点的值。
在插入节点时,我们需要找到合适的位置,将新节点插入到正确的位置上。
四、删除节点删除节点是从二叉树中移除节点的操作。
删除节点的过程相对复杂,需要考虑多种情况。
如果要删除的节点是叶子节点,直接删除即可。
如果要删除的节点只有一个子节点,将其子节点连接到父节点上。
如果要删除的节点有两个子节点,我们需要找到其后继节点或前驱节点来替代被删除的节点。
实验结果:通过实验,我们成功地实现了二叉树的基本操作。
创建二叉树的递归算法能够正确地创建出符合要求的二叉树。
遍历二叉树的算法能够按照指定的顺序遍历每个节点。
插入节点和删除节点的操作也能够正确地修改二叉树的结构。
讨论与总结:二叉树的基本操作是数据结构中的重要内容,对于理解和应用其他数据结构具有重要意义。
通过本次实验,我们深入了解了二叉树的创建、遍历、插入和删除等操作,并通过实验验证了其正确性和有效性。
数据结构实验报告(二叉树的基本操作)
else LeafNum=LeafCount(root->LChild)+LeafCount(root->RChild);
//叶子数为左右子树数目之和
return LeafNum;
printf("\n菜单选择\n\n");
printf(" 1.树状输出二叉树2.先序遍历二叉树\n");
printf(" 3.中序遍历二叉树4.后序遍历二叉树\n");
printf(" 5.输出叶子结点6.输出叶子结点的个数\n");
printf(" 7.输出二叉树的深度8.退出\n");
printf("\n----------------------------------------------------------------------\n");
{
printf("\n\n");
j=j+1; k=0;
while(k<nlocate)
{
printf(" ");
k++;
}
}
while(k<(nlocate-1))
{
printf(" ");
k++;
}
printf("%c",bt->data );
q.front=q.front+1;
if(bt->LChild !=NULL)//存在左子树,将左子树根节点入队列
实验5-二叉搜索树的基本操作(大作业)
浙江大学城市学院实验报告课程名称数据结构与算法实验项目名称实验五二叉搜索树的基本操作学生姓名专业班级计算0 学号30实验成绩指导老师(签名)日期一.实验目的和要求1.掌握二叉搜索树的基本概念。
2.掌握二叉搜索树基本操作的实现。
二. 实验内容1.设在一棵二叉搜索树的每个结点的data域中,含有关键字key域和统计相同关键字元素个数的count域。
当向该树插入一个元素时,若树中已有相同关键字值的结点,则使该结点的count域值增1,否则由该元素值生成一个新结点插入到该树中,并使其count域置为1。
当向该树删除一个元素时,若树中该元素结点的count域值大于1,则使该结点的count域值减1,否则(count域值等于1)删除该结点。
请编写程序实现该二叉搜索树的下述基本操作:①初始化该二叉搜索树void InitBSTree(BTreeNode *&bst);②以广义表形式输出该二叉搜索树(每个结点输出内容包括关键字值与相同元素个数值)void PrintBSTree(BTreeNode *bst);③插入一个元素到该二叉搜索树(用非递归算法实现)void Insert(BTreeNode *&bst, ElemType item);④从二叉搜索树中删除某个元素(用非递归算法实现)int Delete(BTreeNode *&bst , ElemType item)。
⑤求该二叉搜索树的最大关键字值(用非递归算法实现)ElemTypeMaxBSTree(BTreeNode *bst)。
把二叉搜索树的结构定义及基本操作实现函数存放在文件BSTree.h中。
2.建立主程序文件test5.cpp,在主函数main()中通过调用BSTree.h中的函数进行测试。
提示:可以在主函数中首先初始化二叉搜索树;然后从键盘输入数据,通过循环调用插入算法建立二叉搜索树;再以广义表形式输出该二叉搜索树;输出二叉搜索树中的最大结点值;最后调用删除算法删除某元素,并输出删除后的二叉搜索树。
二叉树的基本操作实验
图(1)
图表1
else if(a==4)
{
printf("层序遍历:");
howmuch(T,2);
}
else if(a==5)
{
printf("总节点数:");
howmuch(T,0);
}
else if(a==6)
{
printf("总叶子数:");
howmuch(T,1);
}
else if(a==7)
{
printf("树的深度:");
二 概要设计
功能实现
1.int CreatBiTree(BiTree &T)用递归的方法先序建立二叉树, 并用链表储存该二叉树
2.int PreTravel(BiTree &T)前序遍历
3.intMidTravel(BiTree &T)中序遍历
4.intPostTravel(BiTree &T)后序遍历
实验三 二叉树的基本运算
一、实验目的
1、使学生熟练掌握二叉树的逻辑结构和存储结构。
2、熟练掌握二叉树的各种遍历算法。
二、实验内容
[问题描述]
建立一棵二叉树,试编程实现二叉树的如下基本操作:
1. 按先序序列构造一棵二叉链表表示的二叉树T;
2. 对这棵二叉树进行遍历:先序、中序、后序以及层次遍历,分别输出结点的遍历序列;
5.int Depth(BiTree &T) //计算树的深度
6.inthowmuch(BiTree T,int h)采用树节点指针数组,用于存放遍历到的元素地址,如果有左孩子,存入地址,j加一 ,否则没操作,通过访问数组输出层次遍历的结果。k计算叶子数,j为总节点。
二叉排序树的基本操作
二叉排序树的基本操作
二叉排序树
二叉排序树(Binary Sort Tree),又称二叉查找树、二叉搜索树,是指一棵空
树或者具有下列性质的二叉树:
二叉排序树的基本操作
二叉排序树包括了以下几种基本操作:
在二叉排序树中插入新的数据是就是将新的数据和二叉排序树中的节点进行比较,如果新的数据比节点的数据小,就将新的数据放在节点的左边;如果新的数据比节点的数据大,就将新的数据放在节点的右边,这样对整棵树依次重复比较,直到找到一个空节点位置将新数据插入进去。
删除操作是比较复杂的,需要做三步:第一步是查找到要删除的节点;第二步是找到这个节点的“前驱”节点;第三步是将“前驱”节点替换到要删除的节点上。
具体步骤:
查找操作是最常用的操作。
查找操作的思路与插入操作有点类似,也是用新数据和二叉排序树中的节点进行比较。
如果新的数据比节点的数据小,就转到左子树;如果新的数据比节点的数据大,就转到右子树,这样就能够找到新数据在二叉排序树中的位置。
总结
二叉排序树是一种应用比较广泛的数据结构,它具有查找、插入、删除等常见数据操作方式。
其中,插入操作是将新数据依次与树中节点进行比较,如果新数据比节点的数据小,就放在节点的左边;而查找操作则是和插入操作相似,只不过是找所需要的数据而已。
最后,删除操作则需要先找到要删除的节点,然后找到“前驱”节点并将其替换到要删除的节点上,最终再将“前驱”节点删除。
二叉树基本操作
二叉树基本操作二叉树基本操作一、实验目的1.熟悉二叉树结点的结构和对二叉树的基本操作。
2.掌握对二叉树每一种操作的具体实现。
3.学会利用递归方法编写对二叉树这种递归数据结构进行处理的算法。
4.在二叉树基本操作的基础上掌握对二叉树的一些其它操作的具体实现方法。
5.掌握构造哈夫曼树以及哈夫曼编码的方法。
二、实验内容(必做1)程序 1该程序的功能是实现二叉树结点的类型定义和对二叉树的基本操作。
该程序包括二叉树结构类型以及每一种操作的具体的函数定义和主函数。
/* 定义 DataType 为char类型 */typedef char DataType;/* 二叉树的结点类型 */typedef struct BitNode{DataType data;struct BitNode *lchild,*rchild;}BitNode,*BitTree;/* 初始化二叉树,即把树根指针置空 */void BinTreeInit(BitTree *BT)/* 按先序次序建立一个二叉树*/void BinTreeCreat(BitTree *BT)/* 检查二叉树是否为空 */int BinTreeEmpty(BitTree *BT)/* 按任一种遍历次序(包括按先序、中序、后序、按层次)输出二叉树中的所有结点 */void BinTraverse(BitTree *BT)/* 求二叉树的深度 */int BinTreeDepth(BitTree BT)/* 求二叉树中所有结点数 */int BinTreeCount(BitTree BT)/* 清除二叉树,使之变为空树 */void BinTreeClear(BitTree *BT)程序2 二叉树采用二叉链表存储,设计按层次遍历二叉树的算法。
设计要求:在程序中构造两个子程序分别为void BinTreeCreat(BitTree *BT) /* 按前序次序建立一个二叉树*/ void layorder(BitTree T) /*按层次遍历二叉树 */程序 3哈夫曼树和哈夫曼编码:从终端输入若干个字符,统计字符出现的频率,将字符出现的频率作为结点的权值,建立哈夫曼树,然后对各字符进行哈夫曼编码。
二叉搜索树操作方法
二叉搜索树操作方法二叉搜索树(Binary Search Tree,BST)是一种特殊的二叉树,其中每个节点的左子树中的所有节点都小于该节点的值,右子树中的所有节点都大于该节点的值。
BST可以用于快速地插入、删除和搜索数据。
以下是二叉搜索树的常见操作方法:1. 插入节点(Insertion):从根节点开始,将要插入的节点与当前节点进行比较。
若要插入的节点小于当前节点,则在当前节点的左子树上递归插入;若要插入的节点大于当前节点,则在当前节点的右子树上递归插入;若要插入的节点等于当前节点,则放弃插入(假设不允许重复节点)。
插入节点的时间复杂度为O(h),其中h是树的高度。
2. 删除节点(Deletion):先找到要删除的节点。
若要删除的节点没有子节点,则直接删除它;若要删除的节点只有一个子节点,则将其子节点提升到当前节点的位置;若要删除的节点有两个子节点,则找到它的后继节点(即大于该节点的最小节点)或前驱节点(即小于该节点的最大节点),将后继节点或前驱节点的值替换到要删除的节点上,然后再在后继节点或前驱节点所在子树上递归删除后继节点或前驱节点。
删除节点的时间复杂度为O(h),其中h是树的高度。
3. 搜索节点(Search):从根节点开始,将要搜索的值与当前节点进行比较。
若要搜索的值小于当前节点,则在当前节点的左子树上递归搜索;若要搜索的值大于当前节点,则在当前节点的右子树上递归搜索;若要搜索的值等于当前节点,则找到了目标节点。
搜索节点的时间复杂度为O(h),其中h是树的高度。
4. 最小值(Minimum):从根节点开始,一直沿左子树走到最左边的节点,即最小值节点。
5. 最大值(Maximum):从根节点开始,一直沿右子树走到最右边的节点,即最大值节点。
6. 中序遍历(In-order Traversal):在BST中,按照左子树-根节点-右子树的顺序遍历所有节点,可以得到升序排列的节点值序列。
7. 销毁(Destruction):从根节点开始,递归销毁左子树和右子树,然后释放当前节点的内存。
实验五--二叉树的存储结构和基本操作
实验五二叉树的存储表示和基本操作实验内容1. 二叉树的二叉链表的存储结构—————二叉树的二叉链表存储表示————————typedef struct node{ElemType data; /*数据元素*/struct node *lchild; /*指向左孩子*/struct node *rchild; /*指向右孩子*/} BTNode;2. 二叉树的基本操作(1)创建操作:创建一棵二叉树。
(2)查找操作:查找二叉树中值为x的结点。
(3)查找左孩子操作:查找二叉树中值为x的结点的左孩子。
(4)查找右孩子操作:查找二叉树中值为x的结点的右孩子。
(5)求深度操作:求二叉树的深度。
(6)求宽度操作:求二叉树的宽度。
(7)求结点个数操作:求二叉树的结点个数。
(8)求叶子结点个数操作:求二叉树的叶子结点个数。
(9)输出操作:以括号表示法输出二叉树。
3. 链式队列操作实现的步骤(1)实现将链式队列的存储结构和基本操作程序代码。
(2)实现main主函数。
4.程序代码完整清单#include <stdio.h>#include <malloc.h>#define MaxSize 100typedef char ElemType;typedef struct node{ElemType data; /*数据元素*/struct node *lchild; /*指向左孩子*/struct node *rchild; /*指向右孩子*/} BTNode;//基本操作函数声明void CreateBTNode(BTNode *&b,char *str); /*创建一棵二叉树*/ BTNode *FindNode(BTNode *b,ElemType x); /*查找二叉树的结点*/ BTNode *LchildNode(BTNode *p); /*查找二叉树结点的左孩子*/ BTNode *RchildNode(BTNode *p); /*查找二叉树结点的右孩子*/ int BTNodeDepth(BTNode *b); /*求二叉树的深度*/void DispBTNode(BTNode *b); /*输出二叉树*/int BTWidth(BTNode *b); /*求二叉树的宽度*/int Nodes(BTNode *b); /*求二叉树结点个数*/int LeafNodes(BTNode *b); /*求二叉树叶子结点个数*/void main(){BTNode *b,*p,*lp,*rp;;CreateBTNode(b,"A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))");printf("\n");printf("(1)输出二叉树:");DispBTNode(b);printf("\n");printf("(2)'H'结点:");p=FindNode(b,'H');if (p!=NULL){lp=LchildNode(p);if (lp!=NULL)printf("左孩子为%c ",lp->data);elseprintf("无左孩子");rp=RchildNode(p);if (rp!=NULL)printf("右孩子为%c",rp->data);elseprintf("无右孩子");}printf("\n");printf("(3)二叉树b的深度:%d\n",BTNodeDepth(b));printf("(4)二叉树b的宽度:%d\n",BTWidth(b));printf("(5)二叉树b的结点个数:%d\n",Nodes(b));printf("(6)二叉树b的叶子结点个数:%d\n",LeafNodes(b));printf("\n");}void CreateBTNode(BTNode *&b,char *str) /*由str串创建二叉链*/{BTNode *St[MaxSize],*p=NULL;int top=-1,k,j=0;char ch;b=NULL; /*建立的二叉树初始时为空*/ch=str[j];while (ch!='\0') /*str未扫描完时循环*/{switch(ch){case '(':top++;St[top]=p;k=1; break; /*为左结点*/case ')':top--;break;case ',':k=2; break; /*为右结点*/default:p=(BTNode *)malloc(sizeof(BTNode));p->data=ch;p->lchild=p->rchild=NULL;if (b==NULL) /*p指向二叉树的根结点*/b=p;else /*已建立二叉树根结点*/{switch(k){case 1:St[top]->lchild=p;break;case 2:St[top]->rchild=p;break;}}}j++;ch=str[j];}}BTNode *FindNode(BTNode *b,ElemType x) /*查找二叉树的结点操作结果:返回data*/ { /* 域为x的结点指针*/BTNode *p;if (b==NULL)return NULL;else if (b->data==x)return b;else{p=FindNode(b->lchild,x);if (p!=NULL)return p;elsereturn FindNode(b->rchild,x);}}BTNode *LchildNode(BTNode *p) /*查找二叉树结点的左孩子操作结果:返回*p*/{ /*结点的左孩子结点指针*/return p->lchild;}BTNode *RchildNode(BTNode *p) /*查找二叉树结点的右孩子操作结果:返回*p结*/ { /*点的右孩子结点指针*/return p->rchild;}int BTNodeDepth(BTNode *b) /*求二叉树b的深度*/{int lchilddep,rchilddep;if (b==NULL)return(0); /*空树的高度为0*/ else{lchilddep=BTNodeDepth(b->lchild); /*求左子树的高度为lchilddep*/rchilddep=BTNodeDepth(b->rchild); /*求右子树的高度为rchilddep*/return (lchilddep>rchilddep)? (lchilddep+1):(rchilddep+1);}}void DispBTNode(BTNode *b) /*以括号表示法输出二叉树*/{if (b!=NULL){printf("%c",b->data);if (b->lchild!=NULL || b->rchild!=NULL){printf("(");DispBTNode(b->lchild);if (b->rchild!=NULL) printf(",");DispBTNode(b->rchild);printf(")");}}}int BTWidth(BTNode *b) /*求二叉树b的宽度*/{struct{int lno; /*结点的层次编号*/BTNode *p; /*结点指针*/} Qu[MaxSize]; /*定义顺序非循环队列*/int front,rear; /*定义队首和队尾指针*/ int lnum,max,i,n;front=rear=0; /*置队列为空队*/if (b!=NULL){rear++;Qu[rear].p=b; /*根结点指针入队*/Qu[rear].lno=1; /*根结点的层次编号为1*/while (rear!=front) /*队列不为空*/{front++;b=Qu[front].p; /*队头出队*/lnum=Qu[front].lno;if (b->lchild!=NULL) /*左孩子入队*/{rear++;Qu[rear].p=b->lchild;Qu[rear].lno=lnum+1;}if (b->rchild!=NULL) /*右孩子入队*/{rear++;Qu[rear].p=b->rchild;Qu[rear].lno=lnum+1;}}max=0;lnum=1;i=1;while (i<=rear){n=0;while (i<=rear && Qu[i].lno==lnum){n++;i++;}lnum=Qu[i].lno;if (n>max) max=n;}return max;}elsereturn 0;}int Nodes(BTNode *b) /*求二叉树b的结点个数*/{int num1,num2;if (b==NULL)return 0;else if (b->lchild==NULL && b->rchild==NULL)return 1;else{num1=Nodes(b->lchild);num2=Nodes(b->rchild);return (num1+num2+1);}}int LeafNodes(BTNode *b) /*求二叉树b的叶子结点个数*/{int num1,num2;if (b==NULL)return 0;else if (b->lchild==NULL && b->rchild==NULL)return 1;else{num1=LeafNodes(b->lchild);num2=LeafNodes(b->rchild);return (num1+num2);}}5. 运行结果清单(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。
二叉查找树案例
二叉查找树案例二叉查找树(Binary Search Tree,简称BST)是一种常用的数据结构,具有以下特点:每个节点的值大于其左子树中任意节点的值,小于其右子树中任意节点的值。
基于这个特性,二叉查找树可以高效地进行插入、查找和删除操作。
下面是一些关于二叉查找树的案例:1. 插入操作:假设有一个空的二叉查找树,我们要依次插入数字5、3、7、2、4、6、8。
首先,将5插入根节点;然后,将3插入5的左子节点;接着,将7插入5的右子节点;再将2插入3的左子节点;将4插入3的右子节点;将6插入7的左子节点;最后,将8插入7的右子节点。
2. 查找操作:假设有一个已经构建好的二叉查找树,我们要查找其中的数字。
以上述插入操作后的二叉查找树为例,如果要查找数字6,我们从根节点开始比较,发现根节点的值为5,小于6,所以继续在右子树中查找。
在7节点处比较,发现节点值等于6,表示找到了目标数字。
3. 删除操作:假设有一个已经构建好的二叉查找树,我们要删除其中的数字。
以上述插入操作后的二叉查找树为例,如果要删除数字3,首先找到要删除的节点。
由于3有两个子节点,我们选择找到左子树中最大的节点或右子树中最小的节点来替代要删除的节点。
在这里,我们选择找到右子树中最小的节点4来替代3。
然后,将4节点的值复制给3节点,再删除4节点即可。
4. 遍历操作:二叉查找树可以按照不同的方式进行遍历,包括前序遍历、中序遍历和后序遍历。
以上述插入操作后的二叉查找树为例,进行中序遍历得到的结果为2、3、4、5、6、7、8。
5. 最小值和最大值:在二叉查找树中,最小的值一定在最左子节点,最大的值一定在最右子节点。
通过向左或向右不断遍历,就可以找到最小值和最大值。
6. 平衡二叉查找树:为了避免二叉查找树在某一侧过于倾斜而导致查找效率下降,可以使用平衡二叉查找树(AVL树)或红黑树进行优化。
7. 查找前驱和后继:在二叉查找树中,节点的前驱是指小于该节点的最大节点,后继是指大于该节点的最小节点。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
浙江大学城市学院实验报告课程名称数据结构与算法实验项目名称实验五二叉搜索树的基本操作学生姓名蓝礼巍专业班级学号实验成绩指导老师(签名)日期一.实验目的和要求1.掌握二叉搜索树的基本概念。
2.掌握二叉搜索树基本操作的实现。
二. 实验内容1. 设在一棵二叉搜索树的每个结点的data域中,含有关键字key域和统计相同关键字元素个数的count域。
当向该树插入一个元素时,若树中已有相同关键字值的结点,则使该结点的count域值增1,否则由该元素值生成一个新结点插入到该树中,并使其count域值为1。
当向该树删除一个元素时,若树中该元素结点的count域值大于1,则使该结点的count域值减1,否则(count 域值等于1)删除该结点。
编写头文件bstree.h,实现上述二叉搜索树的存储结构定义与基本操作实现函数;编写主函数文件test8_1.cpp,验证头文件中各个操作。
基本操作包括:①void InitBSTree(BTreeNode *&bst);//初始化该二叉搜索树②void PrintBSTree(BTreeNode *bst);//以广义表形式输出该二叉搜索树(输出内容包括关键字值与相同元素个数值)③void Insert (BTreeNode *&bst, ElemType item);//插入一个元素到该二叉搜索树(用非递归算法实现)④int Delete (BTreeNode *&bst , ElemType item);//从二叉搜索树中删除某个元素(用非递归算法实现)⑤ElemType MaxBSTree(BTreeNode *bst);//求该二叉搜索树的最大关键字值(用非递归算法实现)2.选做:编写下列操作的实现函数,添加到头文件bstree.h中,并在主函数文件test8_1.cpp中添加相应语句进行测试。
①void PrintNode1(BTreeNode *bst);//按递减序打印二叉搜索树中所有左子树为空,右子树非空的结点数据域的值②void PrintNode2(BTreeNode *bst, int x );//从小到大输出二叉搜索树中所有关键字值>=x 的结点数据域的值3. 填写实验报告,实验报告文件取名为report5.doc。
4. 上传实验报告文件report5.doc与源程序文件bstree.h及test8_1.cpp到Ftp服务器上你自己的文件夹下。
三. 函数的功能说明及算法思路包括每个函数的功能说明,及一些重要函数的算法实现思路1 void InitBSTree(BTreeNode *&bst); //初始化该二叉搜索树2 void PrintBSTree(BTreeNode *bst);//以广义表形式输出该二叉搜索树(输出内容包括关键字值与相同元素个数值)3 void Insert (BTreeNode *&bst, ElemType item); /插入一个元素到该二叉搜索树(用非递归算法实现)4 int Delete (BTreeNode *&bst , ElemType item);/从二叉搜索树中删除某个元素(用非递归算法实现)5 ElemType MaxBSTree(BTreeNode *bst);//求该二叉搜索树的最大关键字值(用非递归算法实现)6 void PrintNode1(BTreeNode *bst); //按递减序打印二叉搜索树中所有左子树为空,右子树非空的结点数据域的值7 void PrintNode2(BTreeNode *bst, int x );/从小到大输出二叉搜索树中所有关键字值>=x 的结点数据域的值四. 实验结果与分析包括运行结果截图等五. 心得体会记录实验感受、上机过程中遇到的困难及解决办法、遗留的问题、意见和建议等。
【附录----源程序】Cpp:/*基本操作包括:①void InitBSTree(BTreeNode *&bst);//初始化该二叉搜索树②void PrintBSTree(BTreeNode *bst);//以广义表形式输出该二叉搜索树(输出内容包括关键字值与相同元素个数值)③void Insert (BTreeNode *&bst, ElemType item);//插入一个元素到该二叉搜索树(用非递归算法实现)④int Delete (BTreeNode *&bst , ElemType item);//从二叉搜索树中删除某个元素(用非递归算法实现)⑤ElemType MaxBSTree(BTreeNode *bst);//求该二叉搜索树的最大关键字值(用非递归算法实现)2. 选做:编写下列操作的实现函数,添加到头文件bstree.h中,并在主函数文件test8_1.cpp中添加相应语句进行测试。
①void PrintNode1(BTreeNode *bst);//按递减序打印二叉搜索树中所有左子树为空,右子树非空的结点数据域的值②void PrintNode2(BTreeNode *bst, int x );//从小到大输出二叉搜索树中所有关键字值>=x 的结点数据域的值*/#include<iostream.h>#include<stdio.h>#include<stdlib.h>#include"bstree.h"void main(){ElemType x;BTreeNode *B;InitBSTree(B);cout<<"请输入二叉搜索树,以0 结束"<<endl;cin>>x.key;while(x.key!=0){Insert(B,x);cin>>x.key;}cout<<"以广义表形式输出该二叉搜索树(输出内容包括关键字值与相同元素个数值):"<<endl;PrintBSTree(B);cout<<endl;cout<<"该二叉搜索树的最大关键字值:"<<endl;printf("%d\n",MaxBSTree(B));cout<<"输入要删除的元素的关键值:";cin>>x.key;if(Delete(B,x)!=0){cout<<"以广义表形式输出该二叉搜索树(输出内容包括关键字值与相同元素个数值)"<<endl;PrintBSTree(B);cout<<endl;}cout<<"按递减序打印二叉搜索树中所有左子树为空,右子树非空的结点数据域的值:"<<endl;PrintNode1(B);cout<<endl;cout<<"从小到大输出二叉搜索树中所有关键字值>=x 的结点数据域的值:"<<endl;cout<<"请输入x的值:";cin>>x.key;PrintNode2(B,x.key);cout<<endl;}H:typedef struct{int key;int count;}ElemType;struct BTreeNode{ElemType data;BTreeNode *left;BTreeNode *right;};void InitBSTree(BTreeNode *&bst){bst=NULL;}void PrintBSTree(BTreeNode *&bst){if(bst!=NULL){cout<<"("<<bst->data.key<<","<<bst->data.count<<")";if(bst->left!=NULL||bst->right!=NULL){cout<<"(";PrintBSTree(bst->left);if(bst->right!=NULL)cout<<"(";PrintBSTree(bst->right);cout<<")";}}}void Insert (BTreeNode *&bst, ElemType item) {BTreeNode *t=bst,*parent=NULL,*p;while(t!=NULL){parent=t;if(item.key<t->data.key)t=t->left;else if(item.key>t->data.key)t=t->right;else{t->data.count++;return;}}p=new BTreeNode;p->data.key=item.key;p->data.count=1;p->left=p->right=NULL;if(parent==NULL)bst=p;else if(item.key<parent->data.key)parent->left=p;elseparent->right=p;}int Delete (BTreeNode *&bst , ElemType item) {BTreeNode *p=bst,*fp=NULL;while(p!=NULL&&p->data.key!=item.key){fp=p;p=(p->data.key>item.key)?p->left:p->right;}if(p==NULL)cout<<"删除失败!"<<endl;if(p!=NULL)if(p->data.count>1) p->data.count--;else{if(p->left==NULL&&p->right==NULL){ if(fp==NULL){delete p;bst=NULL;}else{if(fp->left==p)fp->left=NULL;elsefp->right=NULL;delete p;}}else if(p->left!=NULL&&p->right!=NULL){ fp=p;BTreeNode *q=fp->left;ElemType temp;while(q->right!=NULL){fp=q;q=q->right;}temp.count=p->data.count;temp.key=p->data.key;p->data.count=q->data.count;p->data.key=q->data.key;q->data.count=temp.count;q->data.count=temp.key;if(q->left==NULL&&q->right==NULL){if(fp->left==p)fp->left=NULL;elsefp->right=NULL;delete p;}else{if(fp->left==p)fp->left=(p->right==NULL)?p->left:p->right;elsefp->right=(p->right==NULL)?p->left:p->right; delete p;}}else{if(fp==NULL){bst=(p->left!=NULL)?p->left:p->right;delete p;}else{if(fp->left==p)fp->left=(p->right==NULL)?p->left:p->right;elsefp->right=(p->right==NULL)?p->left:p->right;delete p;}}}return true;/*BTreeNode *p=bst,fp=NULL;while(p!=NULL&&p->data!=item){fp=p;if(p->data>x)p=p->left;elsep->right;}if(p==NULL)return 0;if(p->left==NULL&&p->right==NULL){if(fp==NULL){delete p;bst=NULL;}else}ElemType MaxBSTree(BTreeNode *bst){BTreeNode *p=bst;ElemType x;if(p==NULL)printf("空树");if(p->right==NULL&&p->left==NULL)return p->data;if(p->right!=NULL){while(p->right!=NULL){x=p->right->data;p=p->right;}return x;}}void PrintNode1(BTreeNode *bst)//按递减序打印二叉搜索树中所有左子树为空,右子树非空的结点数据域的值{if(bst==NULL)return;PrintNode1(bst->right);if(bst->left==NULL&&bst->right!=NULL)cout<<bst->data.key<<" ";PrintNode1(bst->left);}void PrintNode2(BTreeNode *bst, int x )//从小到大输出二叉搜索树中所有关键字值>=x 的结点数据域的值v{if(bst==NULL)return;if(x<bst->data.key){PrintNode2(bst->left,x);cout<<bst->data.key<<" ";PrintNode2(bst->right,x);}else if(x>bst->data.key){PrintNode2(bst->right,x);else if(x==bst->data.key){cout<<bst->data.key<<" ";PrintNode2(bst->right,x);}}。