题目描述建立二叉树并采用先序、中序、后序遍历二叉树。
本次创建二叉树的方法采用 AB…C…的方法(A为根结点,B为左节点,C为右节点,B,C均为孩子节点)
递归分析:理解二叉树,要从本质入手,最本质的思想就是递归。传入函数根结点,每一个孩子节点其实就是下一个孩子节点的父亲节点,就相当于根节点。很明显与递归思想类似,将问题拆分为小问题,从小问题入手。
非递归分析,在数据结构前面,我们可以使用栈来消除递归,这是因为递归本质思想还是先进后出。本次一一分析先中后序的非递归方法,但仅提供后序(因为最难)
实验二的代码已全部公开,可进行查看。链接:https://blog.csdn.net/QAZJOU/article/details/120790581
当然为简化程序,本次使用C++STLstack模版,注意是指针类型。
先序:对于任一结点P:
1)访问结点P,并将结点P入栈; 2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P;3)直到P为NULL并且栈为空,则遍历结束。
中序类似先序,只要改变visit函数位置就行。
下面重点谈谈后序。
要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。
全部代码C++,C(只有非递归版)
BiTreeRC.h递归头文件
#pragma once
#ifndef BITREERC_H
#define BITREEC_H
#include <iostream>
#include <malloc.h>
using namespace std;
typedef struct Bitree {
char data;
struct Bitree* Lchild;
struct Bitree* Rchild;
}Bitree,*Bit;
//创建二叉树
void CreatBit(Bit* root) {
char ch;
ch = getchar();
if (ch == '.') *root = NULL;
else {
*root = (Bitree*)malloc(sizeof(Bitree));
(*root)->data = ch;
CreatBit(&((*root)->Lchild));
CreatBit(&((*root)->Rchild));
}
}
void visit(char ch) {
cout << ch<<" ";
}
//先序遍历
void Preorder(Bit root) {
if (root != NULL) {
visit(root->data);
Preorder(root->Lchild);
Preorder(root->Rchild);
}
}
void Inorder(Bit root) {
if (root != NULL) {
Inorder(root->Lchild);
visit(root->data);
Inorder(root->Rchild);
}
}
void Postorder(Bit root) {
if (root != NULL) {
Postorder(root->Lchild);
Postorder(root->Rchild);
visit(root->data);
}
}
#endif // !BITREERC_H
BiTreeNRC.h非递归头文件
#pragma once
#ifndef BITREENRC_H
#define BITREENRC_H
#include "BiTreeRC.h"
#include <stack>
void nInorder(Bit root) {
stack<Bit> v;//建立栈,注意类型
Bit p;
p = root;
while (p != NULL || !v.empty()) {
while (p != NULL) {
v.push(p);
p = p->Lchild;
}
if(!v.empty()) {
p = v.top();
visit(p->data);
v.pop();
p = p->Rchild;
}
}
}
//先序
void nPreorder(Bit root) {
stack<Bit> v;//建立栈,注意类型
Bit p;
p = root;
while (p != NULL || !v.empty()) {
while(p != NULL) {
visit(p->data);
v.push(p);
p = p->Lchild;
}
if(!v.empty()) {
p = v.top();
v.pop();
p = p->Rchild;
}
}
}
void nPostorder(Bit root) {
stack<Bit> s;
Bit cur;
Bit pre = NULL;
s.push(root);
while (!s.empty()) {
cur = s.top();
if ((cur->Rchild == NULL && cur->Lchild == NULL) || (pre != NULL && (pre == cur->Lchild || pre == cur->Rchild))) {
visit(cur->data);
s.pop();
pre = cur;
}
else {
if (cur->Rchild != NULL) {
s.push(cur->Rchild);
}
if (cur->Lchild != NULL) {
s.push(cur->Lchild);
}
}
}
}
#endif // !BITREENRC_H
Main.cpp
#include "BiTreeRC.h"
#include "BiTreeNRC.h"
void Recursion(Bit b);
void Nonrecursion(Bit b);
int main() {
Bit b;
cout << "***请输入树,格式按照先序遍历进行输入***" << endl;
CreatBit(&b);
Recursion(b);
Nonrecursion(b);
}
void Recursion(Bit b) {
cout << "\n递归算法" << endl;
cout << "\n先序遍历" << endl;
Preorder(b);
cout << "\n中序遍历" << endl;
Inorder(b);
cout << "\n后序遍历" << endl;
Postorder(b);
}
void Nonrecursion(Bit b) {
cout << "非递归算法(栈)" << endl;
cout << "\n先序遍历" << endl;
nPreorder(b);
cout << "\n中序遍历" << endl;
nInorder(b);
cout << "\n后序遍历" << endl;
nPostorder(b);
}
运行展示
C语言非递归版
#include<stdio.h>
#include<stdlib.h>
#define BiTreeNode char
#define TRUE 1
#define FALSE 0
#define MAX_SIZE 50
#define StackElementType BiTree
typedef struct Node
{
BiTreeNode data;
struct Node *LChild;
struct Node *RChild;
}Node,*BiTree;
typedef struct
{
StackElementType elem[MAX_SIZE];
int top;
}Stack;
void InitStack(Stack **S) //初始化
{
*S=(Stack*)malloc(sizeof(Stack));
(*S)->top=-1;
}
int IsEmpty(Stack **S) //判空
{
return ((*S)->top==-1?TRUE:FALSE);
}
int IsFull(Stack **S) //判满
{
return ((*S)->top==MAX_SIZE-1?TRUE:FALSE);
}
int Push(Stack **S,StackElementType x) //进栈
{
if((*S)->top==MAX_SIZE-1)
return (FALSE);
(*S)->top++;
(*S)->elem[(*S)->top]=x;
return (TRUE);
}
int Pop(Stack **S,StackElementType *x) //出栈
{
if((*S)->top==-1)
return (FALSE);
else
{
*x=(*S)->elem[(*S)->top];
(*S)->top--;
return (TRUE);
}
}
int GetTop(Stack **S,StackElementType *x) //取栈顶元素
{
if((*S)->top==-1)
return (FALSE);
else
{
*x=(*S)->elem[(*S)->top];
return (TRUE);
}
}
void Visit(BiTreeNode data) //访问结点数据
{
putchar(data);
}
void CreateBiTree(BiTree *bt) //创建二叉树
{
char ch;
ch=getchar();
if (ch=='.')
*bt=NULL;
else
{
*bt=(BiTree)malloc(sizeof(Node));
(*bt)->data=ch;
CreateBiTree(&((*bt)->LChild));
CreateBiTree(&((*bt)->RChild));
}
}
void PreOrder(BiTree root) //先序遍历
{
Stack *s;
BiTree temp=root;
InitStack(&s);
while (temp!= NULL||IsEmpty(&s)!=TRUE)
{
while (temp!= NULL)
{
Visit(temp->data); //访问根节点
if(IsFull(&s)==TRUE)
return;
Push(&s,temp); //根指针进栈
temp=temp->LChild; //遍历左子树
}
if(IsEmpty(&s)!=TRUE)
{
Pop(&s,&temp); //根指针弹栈
temp=temp->RChild; //遍历右子树
}
}
}
void InOrder(BiTree root) //中序遍历
{
Stack *s;
BiTree temp=root;
InitStack(&s);
while(temp!=NULL||IsEmpty(&s)!=TRUE)
{
while(temp!=NULL)
{
if(IsFull(&s)==TRUE)
return;
Push(&s,temp); //根指针进栈
temp=temp->LChild; //遍历左子树
}
if(IsEmpty(&s)!=TRUE)
{
Pop(&s,&temp); //根指针弹栈
Visit(temp->data); //访问根节点
temp=temp->RChild; //遍历右子树
}
}
}
void PostOrder(BiTree root) //后序遍历
{
Stack *s;
BiTree temp=root,flag=NULL;
InitStack(&s);
while(temp!=NULL||IsEmpty(&s)!= TRUE)
{
while(temp!= NULL)
{
if(IsFull(&s)==TRUE)
return;
Push(&s,temp); //根指针进栈
temp=temp->LChild; //遍历左子树
}
if(IsEmpty(&s)!=TRUE)
{
GetTop(&s,&temp);
if(temp->RChild==NULL||temp->RChild==flag)
{
Pop(&s,&temp); //根指针弹栈
Visit(temp->data); //访问根节点
flag=temp;
temp=NULL;
}
else
temp=temp->RChild; //遍历右子树
}
}
}
int main()
{
BiTree bt=NULL;
printf("请按先序序列输入一颗二叉树的结点数据,以'.'来代表空值:");
CreateBiTree(&bt);
printf("先序序列:");
PreOrder(bt);
printf("\n中序序列:");
InOrder(bt);
printf("\n后序序列:");
PostOrder(bt);
putchar('\n');
return 0;
}