• 二叉树的建造、递归与非递归遍历


    #include "stdafx.h"
    #include <iostream>
    #include <stack>
    #include <queue>
    #include <Windows.h>
    using namespace std;
    
    typedef struct _Node
    {
        int data;
        struct _Node *left;
        struct _Node *right;
        bool isVisit;        //用于后序非递归遍历,表示节点是否可以访问
        _Node()
        {
            data = 0;
            left = NULL;
            right = NULL;
            isVisit = false;
        }
    }Node, *PNode;
    
    //****************二叉树的递归建造********************
    //约定:输入0表示该节点的子树为NULL
    void RecurCreate(PNode pRoot)
    {
        int data;
        cin>>data;
        if (0 != data)
        {
            pRoot = new Node;
            pRoot->data = data;
            RecurCreate(pRoot->left);
            RecurCreate(pRoot->right);
        } 
    }
    
    //假定二叉树如下图所示,利用前序和中序、后序与中序可以唯一确定一棵二叉树的原理
    //                       1
    //                     /   \
    //                    2     3
    //                  / \     / \
    //                 4   5   6   7 
    //               / \  /
    //              8   9 10
    
    const int MAX_NUM = 10;                             //二叉树的节点数
    int pre[MAX_NUM] = {1, 2, 4, 8, 9, 5, 10, 3, 6, 7}; //前序遍历的数组
    int mid[MAX_NUM] = {8, 4, 9, 2, 10, 5, 1, 6, 3, 7}; //中序遍历的数组
    int post[MAX_NUM] = {8, 9, 4, 10, 5, 2, 6, 7,3, 1}; //后序遍历的数组
    
    //获取前序数组的data在中序数组的索引
    int GetPositionInMid(int data)
    {
        for (int i = 0; i < MAX_NUM; i++)
        {
            if (mid[i] == data)
            {
                return i;
            }
        }
    }
    
    //利用前序和中序可以唯一确定一棵二叉树
    //参数说明
    // pRoot   —— 需要建造节点的指针引用
    // iPre    —— 表示pRoot节点的左子树(右子树)在前序数组的第一个索引
    // iMid    —— 表示pRoot节点的左子树(右子树)在中序数组的第一个索引
    // length  —— 表示pRoot节点的左子树(右子树)的长度
    void PreAndMidRecurCreate(PNode &pRoot, int iPre, int iMid, int length)
    {
        if (length <= 0)
        {
            return;
        }
        pRoot = new Node;
        pRoot->data = pre[iPre];
        int pos = GetPositionInMid(pre[iPre]);
        PreAndMidRecurCreate(pRoot->left, iPre + 1, iMid, pos - iMid);
        PreAndMidRecurCreate(pRoot->right, iPre + (pos - iMid) + 1, pos + 1, length - (pos - iMid) - 1);
    }
    
    //利用后序和中序可以唯一确定一棵二叉树
    //参数说明
    // pRoot   —— 需要建造节点的指针引用
    // iPost   —— 表示pRoot节点的左子树(右子树)在后序数组的第一个索引
    // iMid    —— 表示pRoot节点的左子树(右子树)在中序数组的第一个索引
    // length  —— 表示pRoot节点的左子树(右子树)的长度
    void PostAndMidRecurCreate(PNode &pRoot, int iPost, int iMid, int length)
    {
        if (length <= 0)
        {
            return;
        }
        pRoot = new Node;
        pRoot->data = post[iPost];
        int pos = GetPositionInMid(post[iPost]);
        PostAndMidRecurCreate(pRoot->left, iPost - 1 - (length - (pos - iMid) - 1), iMid, pos - iMid);
        PostAndMidRecurCreate(pRoot->right, iPost - 1, pos + 1, length - (pos - iMid) - 1);
    }
    
    
    //****************二叉树的递归遍历********************
    
    //前序递归遍历
    void PreRecurTraversal(PNode pRoot)
    {
        if (NULL != pRoot)
        {
            cout<<pRoot->data<<'\t';
            PreRecurTraversal(pRoot->left);
            PreRecurTraversal(pRoot->right);
        }
    }
    
    //中序递归遍历
    void MidRecurTraversal(PNode pRoot)
    {
        if (NULL != pRoot)
        {
            MidRecurTraversal(pRoot->left);
            cout<<pRoot->data<<'\t';
            MidRecurTraversal(pRoot->right);
        }
    }
    
    //序后递归遍历
    void PostRecurTraversal(PNode pRoot)
    {
        if (NULL != pRoot)
        {
            PostRecurTraversal(pRoot->left);
            PostRecurTraversal(pRoot->right);
            cout<<pRoot->data<<'\t';
        }
    }
    
    //****************二叉树的非递归遍历********************
    
    //第一种前序非递归遍历
    void PreTraversalOne(PNode pRoot)
    {
        PNode pTree = pRoot;
        stack<PNode> s;
        while (!s.empty() || NULL != pTree)
        {
            while (NULL != pTree)
            {
                cout<<pTree->data<<'\t';
                s.push(pTree);
                pTree = pTree->left;
            }
            if (!s.empty())
            {
                pTree = s.top();
                s.pop();
                pTree = pTree->right;
            }
        }
    }
    
    //第二种前序非递归遍历
    void PreTraversalTwo(PNode pRoot)
    {
        PNode pTree = pRoot;
        stack<PNode> s;
        s.push(pTree);
        while (!s.empty())
        {
            pTree = s.top();
            cout<<pTree->data<<'\t';
            s.pop();
            if (NULL != pTree->right) //1、右子树进栈
            {
                s.push(pTree->right);
            }
            if (NULL != pTree->left) //2、左子树进栈
            {
                s.push(pTree->left);
            }
        }
    }
    
    //中序非递归遍历
    void MidTraversal(PNode pRoot)
    {
        PNode pTree = pRoot;
        stack<PNode> s;
        while (!s.empty() || NULL != pTree)
        {
            while (NULL != pTree)
            {
                s.push(pTree);
                pTree = pTree->left;
            }
            if (!s.empty())
            {
                pTree = s.top();
                cout<<pTree->data<<'\t';
                s.pop();
                pTree = pTree->right;
            }
        }
    }
    
    //后序非递归遍历
    void PostTraversal(PNode pRoot)
    {
        PNode pTree = pRoot;
        stack<PNode> s;
        while (!s.empty() || NULL != pTree)
        {
            while (NULL != pTree)
            {
                s.push(pTree);
                pTree = pTree->left;
            }
            if (!s.empty())
            {
                pTree = s.top();
                if (pTree->isVisit)
                {
                    cout<<pTree->data<<'\t';
                    s.pop();
                    pTree = NULL;
                }
                else
                {
                    pTree->isVisit = true;
                    pTree = pTree->right;
                }
            }
        }
    }
    
    //层序非递归遍历——用队列,注意与第二种非递归前序遍历的区别
    void LevelTraversal(PNode pRoot)
    {
        PNode pTree = pRoot;
        queue<PNode> q;
        q.push(pTree);
        while (!q.empty())
        {
            pTree = q.front();
            q.pop();
            cout<<pTree->data<<'\t';
            if (NULL != pTree->left)  //1、左子树进队列
            {
                q.push(pTree->left);
            }
            if (NULL != pTree->right) //2、右子树进队列
            {
                q.push(pTree->right);
            }
        }
    }
    
    //辅助函数,设置控制台的颜色
    void SetConsoleTextColor(WORD dwColor)
    {
        HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
        if (INVALID_HANDLE_VALUE == handle)
        {
            return;
        }
        SetConsoleTextAttribute(handle, dwColor);
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        PNode pRoot1 = NULL;
        PNode pRoot2 = NULL;
    
        cout<<endl<<"******************根据前序和中序建造二叉树********************"<<endl<<endl;
        PreAndMidRecurCreate(pRoot1, 0, 0, MAX_NUM);
        
        SetConsoleTextColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
        cout<<endl<<"******************层序遍历二叉树********************"<<endl<<endl;
        LevelTraversal(pRoot1);
        SetConsoleTextColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
        cout<<endl<<"******************递归遍历二叉树********************"<<endl<<endl;
        cout<<endl<<"       **********前序递归遍历二叉树**********"<<endl<<endl;
        PreRecurTraversal(pRoot1);
        cout<<endl<<"       **********中序递归遍历二叉树**********"<<endl<<endl;
        MidRecurTraversal(pRoot1);
        cout<<endl<<"       **********后序递归遍历二叉树**********"<<endl<<endl;
        PostRecurTraversal(pRoot1);
    
        SetConsoleTextColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
        cout<<endl<<"******************根据后序和中序建造二叉树********************"<<endl<<endl;
        PostAndMidRecurCreate(pRoot2, MAX_NUM - 1, 0, MAX_NUM);
    
        SetConsoleTextColor(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
        cout<<endl<<"******************非递归遍历二叉树********************"<<endl<<endl;
        cout<<endl<<"       **********前序非递归遍历二叉树**********"<<endl<<endl;
        PreTraversalOne(pRoot2);
        cout<<endl;
        PreTraversalTwo(pRoot2);
        cout<<endl<<"       **********中序非递归遍历二叉树**********"<<endl<<endl;
        MidTraversal(pRoot2);
        cout<<endl<<"       **********后序非递归遍历二叉树**********"<<endl<<endl;
        PostTraversal(pRoot2);
        return 0;
    }

    输出效果如图所示

  • 相关阅读:
    仓鼠找sugar(LCA)
    bzoj4481非诚勿扰(期望dp)
    NOIP2011Mayan游戏(模拟)
    [国家集训队]旅游
    NOIP2012疫情控制(二分答案+树上贪心)
    NOIP2017题解
    [SCOI2010]幸运数字(容斥+爆搜)
    [JSOI2008]Blue Mary的战役地图(二分+哈希)
    [湖南集训]谈笑风生(主席树)
    NOIP2016题解
  • 原文地址:https://www.cnblogs.com/venow/p/2623429.html
Copyright © 2020-2023  润新知