您的位置:首页 > 其它

二叉树前中后序遍历的递归版本和非递归版本、队列实现的层次遍历

2015-04-12 23:39 621 查看
/*  数据结构分析与学习专栏
*   Copyright (c) 2015, 山东大学 计算机科学与技术专业 学生
*   All rights reserved.
*   作    者:   高祥
*   完成日期:  2015 年 4 月 12 日
*   版 本 号:018

*任务描述:针对二叉树遍历,实现7种方法
*   1:层次遍历二叉树 ;
*   2:先序遍历二叉树递归实现 ;
*   3:中序遍历二叉树递归实现;
*   4:后序遍历二叉树递归实现 ;
*   5:先序遍历二叉树非递归实现;
*   6:中序遍历二叉树非递归实现 ;
*   7:后序遍历二叉树非递归实现 ;

*主要函数:
*   1.void CreateByPreOrder(BinaryTree &T);//给定完整的先序遍历建树
*   2.void LevelTraverse(BinaryTree T);//层次遍历
*   3.void PreOrderTraverse1(BinaryTree T);//先序遍历递归实现
*   4.void InOrderTraverse1(BinaryTree T);//中序遍历递归实现
*   5.void PostOrderTraverse1(BinaryTree T);//后序遍历递归实现
*   6.void PreOrderTraverse2(BinaryTree T);//先序遍历非递归实现
*   7.void InOrderTraverse2(BinaryTree T);//中序遍历非递归实现
*   8.void PostOrderTraverse2(BinaryTree T);//后序遍历非递归实现
*运行示例
请输入某棵二叉树的先序遍历(若某结点的左/右子结点不存在,用‘#’表示):
ABC##DE#G##F###
层序遍历为:
A B C D E F G

递归版本的先、中、后序遍历:

先序遍历为:
A B C D E G F
中序遍历为:
C B E G D F A
后序遍历为:
C G E F D B A

非递归版本的先、中、后序遍历:

先序遍历为:
A B C D E G F
中序遍历为:
C B E G D F A
后序遍历为:
C G E F D B A

是否继续程序?请输入Y/N(分别代表是、否):Y
请输入某棵二叉树的先序遍历(若某结点的左/右子结点不存在,用‘#’表示):
ABD##EF#G###CH#J##I#K##
层序遍历为:
A B C D E H I F J K G

递归版本的先、中、后序遍历:

先序遍历为:
A B D E F G C H J I K
中序遍历为:
D B F G E A H J C I K
后序遍历为:
D G F E B J H K I C A

非递归版本的先、中、后序遍历:

先序遍历为:
A B D E F G C H J I K
中序遍历为:
D B F G E A H J C I K
后序遍历为:
D G F E B J H K I C A

是否继续程序?请输入Y/N(分别代表是、否):N

*/
#include<iostream>
#include<queue>
#include<stack>
#include<cstdlib>
using namespace std;

typedef char ElemType;

typedef struct BTNode//二叉树结点类型
{
    ElemType data;
    struct BTNode *leftchild;
    struct BTNode *rightchild;
} BTNode,*BinaryTree;

void CreateByPreOrder(BinaryTree &T);//给定完整的先序遍历建树
void LevelTraverse(BinaryTree T);//层次遍历
void PreOrderTraverse1(BinaryTree T);//先序遍历递归实现
void InOrderTraverse1(BinaryTree T);//中序遍历递归实现
void PostOrderTraverse1(BinaryTree T);//后序遍历递归实现
void PreOrderTraverse2(BinaryTree T);//先序遍历非递归实现
void InOrderTraverse2(BinaryTree T);//中序遍历非递归实现
void PostOrderTraverse2(BinaryTree T);//后序遍历非递归实现

int main()
{
    char operate='y';

    while(operate=='y'||operate=='Y')
    {
        BinaryTree T;

        cout<<"请输入某棵二叉树的先序遍历(若某结点的左/右子结点不存在,用‘#’表示):\n";
        CreateByPreOrder(T);

        cout<<"层序遍历为:\n";
        LevelTraverse(T);

        cout<<"\n递归版本的先、中、后序遍历:\n";
        cout<<"\n先序遍历为:\n";
        PreOrderTraverse1(T);
        cout<<"\n中序遍历为:\n";
        InOrderTraverse1(T);
        cout<<"\n后序遍历为:\n";
        PostOrderTraverse1(T);

        cout<<"\n\n非递归版本的先、中、后序遍历:\n";
        cout<<"\n先序遍历为:\n";
        PreOrderTraverse2(T);
        cout<<"\n中序遍历为:\n";
        InOrderTraverse2(T);
        cout<<"\n后序遍历为:\n";
        PostOrderTraverse2(T);

        cout<<"\n\n是否继续程序?请输入Y/N(分别代表是、否):";
        cin>>operate;
    }
    return 0;
}

void CreateByPreOrder(BinaryTree &T)//给定完整的先序遍历建树
{
    ElemType ch;
    cin>>ch;
    if(ch=='#')
    {
        T=NULL;//空结点
    }
    else
    {
        T=(BinaryTree)malloc(sizeof(BTNode));//建立根结点
        T->data=ch;
        CreateByPreOrder(T->leftchild);//建立当前根结点的左子结点
        CreateByPreOrder(T->rightchild);//建立当前根结点的右子结点
    }
}

void LevelTraverse(BinaryTree T)//层次遍历
{
    if(T)
    {
        //利用数据结构队列实现:首先将根结点入队。在队列不为空的前提下:
        //取出队列首元素T,输出其值并删除队列首元素,若T的左子结点存在,将其入队;
        //若T的右子结点存在,将其入队。重复该过程直至队列为空。
        queue<BinaryTree> Q;
        Q.push(T);//根结点入队

        while(!Q.empty())//在队列不为空的前提下
        {
            BinaryTree now=Q.front();//取出队列首元素T
            cout<<now->data<<" ";//输出其值
            Q.pop();//删除队列首元素

            if(now->leftchild)//若T的左子结点存在,将其入队
            {
                Q.push(now->leftchild);
            }

            if(now->rightchild)//若T的右子结点存在,将其入队
            {
                Q.push(now->rightchild);
            }
        }
        cout<<endl;
    }
}

void PreOrderTraverse1(BinaryTree T)//先序遍历递归实现
{
    if(T)
    {
        cout<<T->data<<" ";//访问根结点
        PreOrderTraverse1(T->leftchild);//访问左子结点
        PreOrderTraverse1(T->rightchild);//访问右子结点
    }
}

void InOrderTraverse1(BinaryTree T)//中序遍历递归实现
{
    if(T)
    {
        InOrderTraverse1(T->leftchild);//访问左子结点
        cout<<T->data<<" ";//访问根结点
        InOrderTraverse1(T->rightchild);//访问右子结点
    }
}

void PostOrderTraverse1(BinaryTree T)//先序遍历递归实现
{
    if(T)
    {
        PostOrderTraverse1(T->leftchild);//访问左子结点
        PostOrderTraverse1(T->rightchild);//访问右子结点
        cout<<T->data<<" ";//访问根结点
    }
}

void PreOrderTraverse2(BinaryTree T)//先序遍历非递归实现
{
    stack<BinaryTree> s;
    while(!s.empty()||T)
    {
        while(T)
        {
            cout<<T->data<<" ";//访问根结点
            s.push(T);//压入访问过的根结点
            T=T->leftchild;//访问当前根结点的左子结点
        }
        //至此为止:所有栈内的结点及其左子结点均已访问完毕

        T=s.top();//取出最后访问过的根结点
        s.pop();//删除栈首元素

        T=T->rightchild;//将当前根结点的右子结点更新为新的根结点(如果存在的话)
    }
}

void InOrderTraverse2(BinaryTree T)//中序遍历非递归实现
{
    stack<BinaryTree> s;
    while(!s.empty()||T)
    {
        while(T)
        {
            s.push(T);//压入根结点但不访问
            T=T->leftchild;//将当前根结点的左子结点更新为新的根结点(如果存在的话)
        }
        //至此为止:所有栈内的结点的左子结点均已访问完毕

        T=s.top();//取出最后压入的根结点(该根结点的左子结点为空)
        cout<<T->data<<" ";//访问该根结点
        s.pop();//栈首元素出栈

        T=T->rightchild;//将当前根结点的右子结点更新为新的根结点(如果存在的话)
    }
}

void PostOrderTraverse2(BinaryTree T)//后序遍历非递归实现
{
    //后序遍历中,二叉树的根结点需要其左右子树都遍历结束后才能访问,需要两个栈来辅助解决
    stack<BinaryTree> s;//指针栈来存放所经过的根结点的指针
    stack<int> num;//辅助栈用来记录某根结点被路过的次数

    while(T||!s.empty())
    {
        while(T)
        {
            s.push(T);//压入根结点不访问
            num.push(1);//第一次路过该根结点
            T=T->leftchild;//将当前根结点的左子结点更新为新的根结点(如果存在的话)
        }

        if(!num.empty())//辅助栈非空时
        {
            if(num.top()==1)
            {
                num.top()=2;//第二次路过当前根结点
                T=s.top();//取出该根结点
                T=T->rightchild;//将当前根结点的右子结点更新为新的根结点(如果存在的话)
            }
            else//第三次路过该当前根结点
            {
                T=s.top();//取出根结点
                s.pop();//指针栈删除栈首元素
                num.pop();//辅助栈删除栈首元素
                cout<<T->data<<" ";//访问当前根结点
                T=NULL;//将访问过的结点置空
            }
        }
    }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐