文章中部分参考了百度以及CSDN上大佬的代码,例如层次遍历那部。代码中的注释是自己编写,可以更好理解。二叉树的遍历还有一种可以不用递归的方法,此处并没写。仅供参考。
#include<iostream>
#include<string.h>
using namespace std;
#define MAX 100
typedef struct bitree
{
char data;
struct bitree *lchild;
struct bitree *rchild;
}Binode,*Bitree;//结构体 Bitree是指针类型
void createBiTree(Bitree &bt)//建立二叉树
{
char ch;//定义一个字符变量
cin>>ch;//输入字符
if(ch=='#')//#是此节点为空的条件
{
bt=NULL;// 树为空
return;//直接带回
}
bt=new Binode;//申请一个新节点
bt->data=ch;//将输入的字符赋值给根节点
createBiTree(bt->lchild);//采用递归建立树的左子树和右子树
createBiTree(bt->rchild);
}
void preOrder(Bitree bt)//先序遍历
{
if(bt){//树不为空
cout<<bt->data<<" ";//先输出根节点
preOrder(bt->lchild);//采用递归先序遍历左子树和右子树
preOrder(bt->rchild);
}
}
void inOrder(Bitree bt)//中序遍历
{
if(bt){
inOrder(bt->lchild);
cout<<bt->data<<" ";//中间输出根节点
inOrder(bt->rchild);
}
}
void postOrder(Bitree bt)//后续遍历
{
if(bt){
postOrder(bt->lchild);
postOrder(bt->rchild);
cout<<bt->data<<" ";//最后输出根节点
}
}
void levelOrder(Bitree bt)//层序遍历,采用队实现
{
Bitree Queue[MAX],b;// 创建一个结构体类型的数组(作为队列)和 b对象;
int front,rear;//定义队尾队首下标
front=rear=0;//初始化队尾和队首为0
if(bt)//树不为空
{
Queue[rear++]=bt;//将根节点入队
while(front!=rear)//队不为空
{
b=Queue[front++]; //将队首元素(即根节点)赋给b;
cout<<b->data<<" ";//输出b的数据域
if(b->lchild!=NULL)//左子树不为空
Queue[rear++]=b->lchild;//左子树进队
if(b->rchild!=NULL)//右子树不为空
Queue[rear++]=b->rchild;//将右子树入队
}
}
}
void FpreOrder(Bitree bt)//非递归先序遍历算法
{
Bitree Stack[MAX],p;//结构体类型的栈Stack
int top = -1;// 栈顶下标
Stack[++top] = bt;//将根节点入栈
while(top!= -1)//栈不为空
{
p = Stack[top--];//栈顶元素即根节点赋值给p
cout << p->data << " ";
if(p->rchild)
Stack[++top] = p->rchild;//右子树入栈
if(p->lchild)
Stack[++top] = p->lchild;//左子树入栈
}
}
void FinOrder(Bitree bt)//迭代中序遍历2
{
if(bt != NULL)//树不为空
{
Bitree Stack[MAX],p;//定义一个结构体类型的栈和p指针
int top = -1;//栈顶下标初始化-1
p =bt;//把二叉树赋给p
while (top != -1 || p != NULL)//栈不为空且p不为空
{
if (p != NULL)//p不为空
{
Stack[++top] = p;//p入栈
p = p->lchild;//p指向左子树
}//左子树入栈
else//栈不为空
{
p = Stack[top--];//p等于栈顶元素 最左的节点弹出
cout << p->data <<' ';//输出根节点
p = p->rchild;//p指向右子树,接下来右子树入栈 ,遍历右子树
}
}
}
}
int FpostOrder(Bitree bt)
{
Bitree p = bt, Stack[MAX], pre;//
int top = 0, flag = 1;
if(p)
do{
while(p)
{
Stack[top++] = p;
p = p->lchild;
} // p所有左节点入栈
flag = 1;
while(top != 0 && flag == 1)
{
p = Stack[top-1];//取栈顶元素但不输出
if(p->rchild == pre || p->rchild == NULL)
{
//右孩子不存在或右孩子已访问
top--;
cout<< p->data<<' ';
pre = p; //指向被访问节点
}
else {
//继续遍历右子树
p = p->rchild;
flag = 0;//
}
}
}while(top != 0);
return 1;
}//
void print(Bitree bt)
{
int n;
cout<<"选择你想采用的遍历的方法;1先序,2中序,3后序,4层序,5非递归先序,6非递归中序,7非递归后序,0结束:" <<endl;
cin>>n;
while(n)
{
if(n==1)
{
cout<<"输出先序遍历的结果:";
preOrder(bt);
}
if(n==2)
{
cout<<"输出中序遍历的结果:";
inOrder(bt);
}
if(n==3)
{
cout<<"输出后序遍历的结果:";
postOrder(bt);
}
if(n==4)
{
cout<<"输出层次遍历的结果:";
levelOrder(bt);
}
if(n==5)
{
cout<<"输出非递归先序遍历的结果:";
FpreOrder(bt);
}
if(n==6)
{
cout<<"输出非递归中序遍历的结果:";
FinOrder(bt);
}
if(n==7)
{
cout<<"输出非递归后序遍历的结果:";
FpostOrder(bt);
}
/*if(n!=1&&n!=2&&n!=3&&n!=4&&n!=5&&n!=6&&n!=7)
cout<<"输入错误,请重新选择:";*/
while(n>7)
{
cout<<"输入错误,请重新选择!"<<endl;
break;
}
cout<<endl;
//cout<<"选择你想采用的遍历的方法:1 先序,2 中序,3 后序,4 层序,0 结束:" <<endl;
cin>>n;
}
}
//水平画树,画分支
void draw_level(Bitree bt,bool left,char* str) //bool 在c++中是一个数据类型只有两个选择 返回值只有真true或假flase
{//在此处left是判断左右
if (bt->rchild) {//右子树不为空 (判断左右子树顺序不能调换)
draw_level(bt->rchild,false,strcat(str,(left ? "| " : " ")));//strcat是用来拼接字符串
}//递归 画右子树
cout<<str;
cout<<(left ? '\\': '/');//条件运算符 真(左)则输出'\\'假 (右 )则输出'/'
//反斜杠是转义字符的开头,要使用\\表示,也即'\\'
cout<<"-----";
cout<<bt->data;
cout<<endl;
if (bt->lchild) {
draw_level(bt->lchild, true, strcat(str, (left ? " " : "| ")));
}
str[strlen(str)-6]='\0';//字符串结束
}
void draw(Bitree root) {//根节点画树
char str[MAX];
memset(str, '\0', MAX);//初始化字符串,都赋值为'\0'
if (root->rchild) {
draw_level(root->rchild, false, str);
}//画右子树
cout<<root->data;//输出根节点
cout<<endl;
if (root->lchild) {
draw_level(root->lchild, true, str);
}//画左子树
}
int main()
{
Binode *bt;//创建一个结构体类型的变量bt
char *str;//定义一个字符指针类型的字符串
cout<<endl;
cout<<" 请输入你想添加的节点,输入'#'则此节点为NULL:"<<endl;
createBiTree(bt);//调用创建二叉树的函数
cout<<"二叉树建立成功!"<<endl;
cout<<endl;
cout<<"画出二叉树为:"<<endl;
draw(bt);
print(bt);
return 0;
}