数据结构实验课之二叉树实验(一)
该博客待完善,编者目前为大二学生水平较差,内容仅供参考
实验内容:
以括号表示法作为输入字符串构造一棵二叉树,完成下列实验要求:
(1)如果输入字符串不符合规范,显示错误信息:“输入错误”。
(2)分别显示该二叉树的先序、中序和后序遍历。
(3)求出该二叉树的高度。
(4)输出该二叉树所有的叶子结点。
(5)找出二叉树中的最大、最小值结点,并写出他们的所在层数
令人心碎,其中(2)(3)(4)(5)教材上都有对应类似代码实现起来并不难,个人觉得难点主要在(1)中检查输入是否合法,即括号表示法合法性检查这一块内容。
我一共想到了以下几种非法输入(因个人能力有限,肯定还有没想到的点,希望大家能指正包含)。
1.一对括号中逗号数超过两个,例如A(B,C,D) ,非法
2. 形如 (B,C) 即在第一个左括号前少一个字符,非法
3.形如AA(B,C) ,即数据超过一个字符,非法。 注:本例中我默认数据元素只有一个字符
4.形如 A()) A)))((( ,类似左右括号不匹配,非法。
5.形如A(B,C)D ,类似错误
实现代码如下
#include<bits/stdc++.h>
#define Max 100000
using namespace std;
char Tmax;//最大值节点
char Tmin;//最小值节点
int k1,k2;
struct node
{
char data;
node * lchild;
node * rchild;
};
bool CreateBTree(node * &b,string str)
{
stack<char>q; //判断输入合法性用的栈
bool flag=true;//是否合法标记
//bool zm=true;// 输入节点名之后一定要跟一个左括号 如:AA非法
//bool jm=false;//在左括号前是否缺少节点元素判断 如:(A,B) 非法 。false表示还未输入数据元素,true表示已输入节点元素
node *St[Max],*p;
int top=-1,k,j=0;
int Dnum=0;//逗号数量
char ch;
b=NULL;
ch=str[j];
while(ch!='\0' && flag)
{
switch(ch)
{
case '(':
//if(!jm)flag=false;
//jm=false;//输入左括号后一定要跟一个节点元素 A(B,C)
if(q.empty()){cout<<"左括号前缺少数据元素"<<endl;flag=false;break;}//如果栈为空,即左括号前没有数据元素时,非法输入
top++;
St[top]=p;
k=1;
q.push(ch);
Dnum=0;//输入右括号后逗号数初始化0
break;
case ')':
//cout<<"test1"<<endl;
//if(q.empty())cout<<'1'<<endl;
top--;
while(!q.empty() && q.top()!='(')
{
if(q.top()==',' && Dnum>0)Dnum--;
q.pop();
}
if(q.empty()) //在获取栈顶元素前一定要判断栈是否为空,如果为空强行获取栈顶元素程序会报错
{
flag=false;
cout<<"左右括号不匹配"<<endl;
break;
}
else if(q.top()=='(')
{
q.pop();
}
break;
case ',':
k=2;
Dnum++;
q.push(ch);
if(Dnum>=2)
{
flag=false;
cout<<"逗号数量大于1个"<<endl;
}
break;
default:
p=new node;
p->data=ch;
p->lchild=p->rchild=NULL;
if(q.empty() || q.top()=='(' || q.top()==','||ch==',')//如果栈为空或者栈顶元素为'('将数据元素入栈
{
q.push(ch);
}
else //否则非法
{
flag=false;
cout<<"数据元素输入过多(数据元素只允许一个字符)或某数据元素前一个字符不是左括号"<<endl;
//cout<<"test4"<<endl;
//cout<<q.top()<<endl;//test
//cout<<ch<<endl;//test
break;
}
if(b==NULL)
b=p;
else
{
switch(k)
{
case 1:St[top]->lchild=p;break;
case 2:St[top]->rchild=p;break;
}
}
}
if(flag==false)
{
//cout<<"输入不合法,括号失配"<<endl;
return flag;
}
j++;
ch=str[j];
}
if(q.size()!=1)
{
flag=false;
cout<<"栈剩余元素大于1,左右括号匹配失败或其他未满足格式情况"<<endl;
//int tmp=q.size(); test
//cout<<tmp<<endl;
}
return flag;
}
void PreOrder(node *b)//先序遍历
{
if(b!=NULL)
{
cout<<b->data<<' ';
PreOrder(b->lchild);
PreOrder(b->rchild);
}
}
void InOrder(node *b)//中序遍历
{
if(b!=NULL)
{
InOrder(b->lchild);
cout<<b->data<<' ';
InOrder(b->rchild);
}
}
void PostOrder(node *b)//后序遍历
{
if(b!=NULL)
{
PostOrder(b->lchild);
PostOrder(b->rchild);
cout<<b->data<<' ';
}
}
int BTHeight(node *b)//获得树高度的函数
{
int lchildh,rchildh;
if(b==NULL)return 0;
else
{
lchildh=BTHeight(b->lchild);
rchildh=BTHeight(b->rchild);
return (lchildh>rchildh)?(lchildh+1):(rchildh+1);
}
}
void Dischild(node *b)//输出叶子节点
{
if(b!=NULL)
{
if(b->lchild==NULL && b->rchild ==NULL)
cout<<b->data<<' ';
Dischild(b->lchild);
Dischild(b->rchild);
}
}
void getMaxMin(node *b,int k)
{
if(b==NULL) //空树直接返回
return ;
else
{
char temp=b->data ;
k++;
if(temp>Tmax){Tmax=temp;k1=k;}
if(temp<Tmin){Tmin=temp;k2=k;}
getMaxMin(b->lchild ,k);
getMaxMin(b->rchild ,k);
}
}
int main()
{
string s;
bool flag;
node *b;
cin>>s;
while(!CreateBTree(b,s))
{
cout<<"输入错误"<<endl;
cout<<endl;
flag=true;//合法标记重置
b=NULL;//指针重置
cin>>s;//重新输入括号表达式
}
int height=BTHeight(b);
cout<<"先序遍历:"<<endl;
PreOrder(b);
cout<<endl;
cout<<"中序遍历:"<<endl;
InOrder(b);
cout<<endl;
cout<<"后序遍历:"<<endl;
PostOrder(b);
cout<<endl;
cout<<"二叉树的高度为:"<<height<<endl;
cout<<"二叉树的叶子节点为:";
Dischild(b);
cout<<endl;
Tmax='0';
Tmin='z'+1;
getMaxMin(b,0);
cout<<"最大值节点为:"<<Tmax<<" 其所在层数为:"<<k1<<endl;
cout<<"最小值节点为:"<<Tmin<<" 其所在层数为:"<<k2<<endl;
return 0;
}
测试结果图片