好久没刷题了。。。发个实验课的东西充数吧
#include <iostream>
#include<cstdio>
#define prt cout<<"请输入二叉树:"
using namespace std;
struct node{
char c; // 字符数据
node *l,*r; // 左右子树指针
node(char cc){ // 构造函数
c=cc;
l=r=NULL;
}
};
bool checkerror(char str[]); // 声明查错函数
node *creat(char str[]){ // 创建新树函数
node *root,*sta[100]; // 定义根节点指针,指针栈
node **p=&root; // 定义指向指针的指针p,并初始化指向根指针
int i=0,top=0;
char c;
while(c=str[i++]){ // 遍历输入的字符串
if(c=='('){ // 若遇见左括号,说明当前节点有儿子
sta[++top]=*p; // 将p指向的指针入栈
p=&(sta[top]->l); // p指向栈顶指针的左儿子指针
}
else if(c==','){ // 若遇见逗号,说明后面要处理的是父节点的右儿子
p=&(sta[top]->r); // p指向栈顶指针的右儿子指针
}
else if(c==')'){ // 若遇见右括号,退栈
top--;
}
else{ // 若遇见字母字符
*p=new node(c); // 为p当前指向的指针申请空间并填充数据
}
}
return root; // 返回根节点指针
}
void preorder(node *root){ // 先序遍历函数
node *p,*sta[200]; // 定义指针栈
int top=0; // sta[0]不存数据,作为栈空的标志
sta[++top]=root; // 将根节点入栈
while(top){ // 当栈不空时进入循环
p=sta[top--]; // 取出栈顶元素并退栈,之后先沿其左子树遍历
while(p!=NULL){ // 若p不为空
cout<<p->c<<' '; // 输出节点数据
sta[++top]=p->r; // 将当前节点的右儿子指针入栈
p=p->l; // p指向其左儿子
}
}
cout<<endl;
}
void inorder(node *root){ // 中序遍历函数
node *p=root,*sta[200];
int top=0;
do{
while(p!=NULL){
sta[++top]=p;
p=p->l;
}
p=sta[top--];
cout<<p->c<<' ';
p=p->r;
}while(top||p!=NULL);
cout<<endl;
}
void postorder(node *root){ // 后序遍历函数
node *p=root,*sta[200];
int top=0;
do{
while(p!=NULL){
sta[++top]=p;
p=p->l;
}
while(top&&sta[top]->r==p){
p=sta[top--];
cout<<p->c<<' ';
}
p=top?sta[top]->r:NULL;
}while(top);
cout<<endl;
}
void bfs(node *root){ // 层次遍历函数
node *p,*que[200];
int l,r; l=r=0;
que[r++]=root;
while(l<r){
p=que[l++];
cout<<p->c<<' ';
if(p->l) que[r++]=p->l;
if(p->r) que[r++]=p->r;
delete p; // 释放空间
}
cout<<endl;
}
int main(){
char str[200];
cout<<"二叉树测试程序,输入Ctrl+Z退出\n";
while(prt,gets(str)){ // prt宏为输出提示信息
if(checkerror(str)) continue; //若输入不合法,不做处理
node *root=creat(str);
cout<<" 先序遍历:"; preorder(root);
cout<<" 中序遍历:"; inorder(root);
cout<<" 后序遍历:"; postorder(root);
cout<<" 层次遍历:"; bfs(root); // 在层次遍历的同时释放内存
cout<<endl;
}
return 0;
}
bool checkerror(char str[]){ // 查错函数
int i=0,tag=3,d=0,vis[200]; // vis[]记录某节点儿子个数,tag记录前一字符的类型,
char c; // 1:'(' 2:')' 3:',' 0:普通字母
vis[0]=1;
while(c=str[i++]){
if(c=='('){
if(tag!=0) break;
tag=1; vis[++d]=0;
}
else if(c==')'){
if(tag==1) break;
tag=2; d--;
}
else if(c==','){
if(tag==3) break;
tag=3; vis[d]++;
}
else{
if(tag==0||tag==2) break;
tag=0;
} //以上为检查字符串格式是否合法
if(d<0||vis[d]>1) break; //通过层数与节点儿子个数,检查逻辑是否合法
}
if(i==1||d>0||c!=0){
cout<<" 输入格式错误!请重新输入!\n\n";
return 1;
}
return 0;
}