• 7. 二叉树遍历( 先序、中序、后序 递归 非递归 )


    RT, 部分参考了《剑指offer》

    #pragma once
    #include <iostream>
    #include <vector>
    #include <stack>
    using namespace std;
    
    struct BinaryTreeNode 
    {
        int m_nValue;
        BinaryTreeNode* m_pLeft;
        BinaryTreeNode* m_pRight;
    };
    
    class BinaryTree
    {
    public:
        BinaryTreeNode* Construct(int preorder[], int inorder[], int length); // 根据先序、中序结果构造二叉树
        BinaryTreeNode* ConstructCore(int* startPreorder, int* endPreOrder, int* startInorder, int* endInorder);
      
    // 递归, 遍历的结果放入vector中
    void PreOrderTraverseRecursion(BinaryTreeNode* root, vector<int>& preOrder); void InOrderTraverseRecursion(BinaryTreeNode* root, vector<int>& inOrder); void PostOrderTraverseRecursion(BinaryTreeNode* root, vector<int>& postOrder);   // 非递归,遍历的结果放入vector中
    void PreOrderTraverseStack(BinaryTreeNode* root, vector<int>& preOrder);
    void InOrderTraverseStack(BinaryTreeNode* root, vector<int>& inOrder);
    void PostOrderTraverseStack(BinaryTreeNode* root, vector<int>& postOrder);
    public:
        BinaryTree(void);
        ~BinaryTree(void);
    
    };
    #include "BinaryTree.h"
    
    
    BinaryTree::BinaryTree(void)
    {
    }
    
    
    BinaryTree::~BinaryTree(void)
    {
    }
    
    BinaryTreeNode* BinaryTree::Construct(int preorder[], int inorder[], int length)
    {
        if (preorder == NULL || inorder == NULL || length < 0)
        {
            return NULL;
        }
        return ConstructCore(preorder, preorder + length - 1, inorder, inorder + length - 1);
    }
    
    BinaryTreeNode* BinaryTree::ConstructCore(int* startPreorder, int* endPreorder, int* startInorder, int* endInorder)
    {
        int rootValue = startPreorder[0];
        BinaryTreeNode* root = new BinaryTreeNode();
        root->m_nValue = rootValue;
        root->m_pLeft = root->m_pRight = NULL;
        if (startPreorder == endPreorder)
        {
            if (startInorder == endInorder && *startInorder == *endInorder) // 叶子结点
            {
                return root;
            }
            else
                throw std::exception("Invalid input.");
        }
    
        // 在中序中找到该value所在位置
        int* rootInorder = startInorder;
        while (rootInorder <= endInorder && *rootInorder != rootValue)
        {
            rootInorder++;
        }
        if (rootInorder > endInorder)
        {
            throw std::exception("Invalid input.");
        }
    
        int leftLength = rootInorder  - startInorder;
        if (leftLength > 0) // 左子树
        {
            root->m_pLeft = ConstructCore(startPreorder + 1, startPreorder + leftLength, startInorder, rootInorder -1);
        }
        if(endInorder - rootInorder > leftLength) // 有右子树
        {
            root->m_pRight = ConstructCore(startPreorder + leftLength + 1, endPreorder, rootInorder + 1, endInorder);
        }
        return root;
    }
    
    
    void BinaryTree::PreOrderTraverseRecursion(BinaryTreeNode* root, vector<int>& preOrder)
    {
        BinaryTreeNode* current = root;
        // 先序递归遍历
        if (current != NULL) 
        {
            preOrder.push_back(current->m_nValue);
            PreOrderTraverseRecursion(current->m_pLeft, preOrder);
            PreOrderTraverseRecursion(current->m_pRight, preOrder); 
        }
    }
    
    void BinaryTree::InOrderTraverseRecursion(BinaryTreeNode* root, vector<int>& inOrder)
    {
        BinaryTreeNode* current = root;
        // 中序递归遍历
        if (current != NULL) 
        {
            InOrderTraverseRecursion(current->m_pLeft, inOrder);
            inOrder.push_back(current->m_nValue);
            InOrderTraverseRecursion(current->m_pRight, inOrder); 
        }
    }
    void BinaryTree::PostOrderTraverseRecursion(BinaryTreeNode* root, vector<int>& postOrder)
    {
        BinaryTreeNode* current = root;
        // 后序递归遍历
        if (current != NULL) 
        {
            PostOrderTraverseRecursion(current->m_pLeft, postOrder);
            PostOrderTraverseRecursion(current->m_pRight, postOrder);
            postOrder.push_back(current->m_nValue);
        }
    }
    
    void BinaryTree::PreOrderTraverseStack(BinaryTreeNode* root, vector<int>& preOrder)
    {
        // 非递归 先序遍历
        BinaryTreeNode* current = root;
        stack<BinaryTreeNode*> travelStack;
        while (current || !travelStack.empty())
        {
            if (current)
            {
                travelStack.push(current);
                preOrder.push_back(current->m_nValue); // 先序
                current = current->m_pLeft;
            }
            else // 左子树为NULL
            {
                current = travelStack.top();
                current = current->m_pRight;
                travelStack.pop(); // 根出栈
            }
        }
    
    }
    
    void BinaryTree::InOrderTraverseStack(BinaryTreeNode* root, vector<int>& inOrder)
    {
        // 非递归 中序遍历
        BinaryTreeNode* current = root;
        stack<BinaryTreeNode*> travelStack;
        while (current || !travelStack.empty())
        {
            if (current)
            {
                travelStack.push(current);
                current = current->m_pLeft;
            }
            else
            {
                current = travelStack.top();
                inOrder.push_back(current->m_nValue); // 中序
                current = current->m_pRight;
                travelStack.pop();
            }
        }
    }
    
    void BinaryTree::PostOrderTraverseStack(BinaryTreeNode* root, vector<int>& postOrder)
    {
        // 非递归 后序遍历
        int flag[1000]; // 使用一个标记,标记该node的右结点是否被访问过
        stack<BinaryTreeNode* > travelStack;
    
        BinaryTreeNode* current = root;
        while(current) // 先左
        {
            travelStack.push(current);
            flag[travelStack.size()] = 0;
            current = current->m_pLeft;
        }
        while(!travelStack.empty())
        {
            current = travelStack.top();
    
            while (current->m_pRight && flag[travelStack.size()] == 0) // 右子树未被访问过
            {
                flag[travelStack.size()] = 1; // 标记当前结点的右子节点被访问过了
                current = current->m_pRight; // 右子树
    
                while(current) // 先左
                {
                    travelStack.push(current);
                    flag[travelStack.size()] = 0;
                    current = current->m_pLeft;
                }
                current = travelStack.top();           
            }
    
            // current的右子树为NULL 或 已被访问过
            postOrder.push_back(current->m_nValue); // 后序访问根结点
            travelStack.pop(); // 出栈
        }
    }
    #include <iostream>
    #include "BinaryTree.h"
    
    using namespace std;
    int main(int agrc, char* argv[])
    {
        BinaryTree bt;
        int preOrder[] = {1,2,4,7,3,5,6,8};
        int inOrder[] = {4,7,2,1,5,3,8,6};
    
        BinaryTreeNode* root = bt.Construct(preOrder, inOrder, 8);
    
        vector<int> preV1;
        vector<int> preV2;
        vector<int> inV1;
        vector<int> inV2;
        vector<int> postV1;
        vector<int> postV2;
        bt.PreOrderTraverseRecursion(root, preV1);
        bt.PreOrderTraverseStack(root, preV2);
        bt.InOrderTraverseRecursion(root, inV1);
        bt.InOrderTraverseStack(root, inV2);
        bt.PostOrderTraverseRecursion(root, postV1);
        bt.PostOrderTraverseStack(root, postV2);
    
        return 0;
    
    }
  • 相关阅读:
    位运算02 零基础入门学习C语言65(完)
    PE格式详细讲解4 系统篇04|解密系列
    PE格式详细讲解4 系统篇04|解密系列
    int指令02 零基础入门学习汇编语言65
    Tabhost漂亮的自定义实现(背景随着选项卡滑动改变)
    Android API Guide 之 User Interface笔记
    java程序员菜鸟进阶(九)windows下搭建SVN服务器及配置myeclipse SVN客户端
    android 左右页面滑动(滑屏)增加layout文件 而不是drawable(还有activity)
    android 最简单的九宫格实现
    ViewPager
  • 原文地址:https://www.cnblogs.com/wenshanzh/p/3293522.html
Copyright © 2020-2023  润新知