二叉树前中后序遍历递归转循环

通过观察递归实现,用循环和栈模拟递归实现中结点入栈和出栈的过程。

#include <bits/stdc++.h>
#define DBG(x) cerr << #x << " = " << x << endl

using namespace std;
typedef long long LL;

struct Node {
    int val;
    Node *left, *right;

    Node() : left(NULL), right(NULL) {}

    Node(int val) : val(val), left(NULL), right(NULL) {}
};

enum StackState {
    AFTER_PUSH_ROOT = 0,
    AFTER_PUSH_LEFT = 1,
    AFTER_PUSH_RIGHT = 2,
};

void dfs_pre_order(Node *root, vector<int> &ret) {
    ret.push_back(root->val);
    if (root->left) dfs_pre_order(root->left, ret);
    if (root->right) dfs_pre_order(root->right, ret);
}

void dfs_in_order(Node *root, vector<int> &ret) {
    if (root->left) dfs_in_order(root->left, ret);
    ret.push_back(root->val);
    if (root->right) dfs_in_order(root->right, ret);
}

void dfs_post_order(Node *root, vector<int> &ret) {
    if (root->left) dfs_post_order(root->left, ret);
    if (root->right) dfs_post_order(root->right, ret);
    ret.push_back(root->val);
}

void pre_order(Node *root, vector<int> &ret) {
    stack<pair<Node *, StackState>> stk;
    stk.push(pair<Node *, StackState>(root, AFTER_PUSH_ROOT));
    while (!stk.empty()) {
        pair<Node *, StackState> &top = stk.top();
        switch (top.second) {
            case AFTER_PUSH_ROOT:
                ret.push_back(top.first->val);
                if (top.first->left) stk.push(pair<Node *, StackState>(top.first->left, AFTER_PUSH_ROOT));
                top.second = AFTER_PUSH_LEFT;
                break;
            case AFTER_PUSH_LEFT:
                if (top.first->right) stk.push(pair<Node *, StackState>(top.first->right, AFTER_PUSH_ROOT));
                top.second = AFTER_PUSH_RIGHT;
                break;
            case AFTER_PUSH_RIGHT:
                stk.pop();
                break;
        }
    }
}

void in_order(Node *root, vector<int> &ret) {
    stack<pair<Node *, StackState>> stk;
    stk.push(pair<Node *, StackState>(root, AFTER_PUSH_ROOT));
    while (!stk.empty()) {
        pair<Node *, StackState> &top = stk.top();
        switch (top.second) {
            case AFTER_PUSH_ROOT:
                if (top.first->left) stk.push(pair<Node *, StackState>(top.first->left, AFTER_PUSH_ROOT));
                top.second = AFTER_PUSH_LEFT;
                break;
            case AFTER_PUSH_LEFT:
                ret.push_back(top.first->val);
                if (top.first->right) stk.push(pair<Node *, StackState>(top.first->right, AFTER_PUSH_ROOT));
                top.second = AFTER_PUSH_RIGHT;
                break;
            case AFTER_PUSH_RIGHT:
                stk.pop();
                break;
        }
    }
}

void post_order(Node *root, vector<int> &ret) {
    stack<pair<Node *, StackState>> stk;
    stk.push(pair<Node *, StackState>(root, AFTER_PUSH_ROOT));
    while (!stk.empty()) {
        pair<Node *, StackState> &top = stk.top();
        switch (top.second) {
            case AFTER_PUSH_ROOT:
                if (top.first->left) stk.push(pair<Node *, StackState>(top.first->left, AFTER_PUSH_ROOT));
                top.second = AFTER_PUSH_LEFT;
                break;
            case AFTER_PUSH_LEFT:
                if (top.first->right) stk.push(pair<Node *, StackState>(top.first->right, AFTER_PUSH_ROOT));
                top.second = AFTER_PUSH_RIGHT;
                break;
            case AFTER_PUSH_RIGHT:
                ret.push_back(top.first->val);
                stk.pop();
                break;
        }
    }
}

Node *get_tree(int num) {
    Node *root = new Node(random());
    vector<Node *> nodes;
    nodes.push_back(root);

    for (int i = 0; i < num; i++) {
        unsigned int pos = random() * random() * random() % nodes.size();
        if (nodes[pos]->left == NULL && nodes[pos]->right == NULL) {
            if (random() % 2 == 0) {
                nodes[pos]->left = new Node(random());
                nodes.push_back(nodes[pos]->left);
            } else {
                nodes[pos]->right = new Node(random());
                nodes.push_back(nodes[pos]->right);
            }
        } else if (nodes[pos]->left) {
            nodes[pos]->right = new Node(random());
            nodes.push_back(nodes[pos]->right);
        } else {
            nodes[pos]->left = new Node(random());
            nodes.push_back(nodes[pos]->left);
        }
        if (nodes[pos]->left && nodes[pos]->right) {
            nodes.erase(nodes.begin() + pos);
        }
    }

    return root;
}

void free_tree(Node *root) {
    if (root->left) free_tree(root->left);
    if (root->right) free_tree(root->right);
    delete root;
}

void test_pre_order() {
    Node *tree = get_tree(100000);
    vector<int> dfs_ret, ret;

    dfs_pre_order(tree, dfs_ret);
    pre_order(tree, ret);
    assert(dfs_ret == ret);

    free_tree(tree);
}

void test_in_order() {
    Node *tree = get_tree(100000);
    vector<int> dfs_ret, ret;

    dfs_in_order(tree, dfs_ret);
    in_order(tree, ret);
    assert(dfs_ret == ret);

    free_tree(tree);
}

void test_post_order() {
    Node *tree = get_tree(100000);
    vector<int> dfs_ret, ret;

    dfs_post_order(tree, dfs_ret);
    post_order(tree, ret);
    assert(dfs_ret == ret);

    free_tree(tree);
}

int main(int argc, char **argv) {
    srand(time(NULL));

    test_pre_order();
    test_in_order();
    test_post_order();

    return 0;
}

原文地址:https://www.cnblogs.com/ToRapture/p/12115657.html

时间: 2024-11-09 03:06:57

二叉树前中后序遍历递归转循环的相关文章

二叉树前中后序遍历非递归实现

package MyExc; import java.util.Stack; class TreeNode{ int data; TreeNode left; TreeNode right; } public class BinaryTree { public void preOrder(TreeNode head){ Stack<TreeNode> stack = new Stack<>(); stack.add(head); while(!stack.isEmpty()){ h

二叉树的前中后序遍历简单的递归

二叉树的遍历 无外乎广度和深度 其中深度又分为前中后序遍历三种情况  这三种遍历若只是递归方法 自然很是简单 但递归代码简单 若嵌套层次太深 会栈溢出 二叉树节点数据结构: struct Binary_node{    int val;    Binary_node *left;    Binary_node *right;    Binary_node(int v = 0, Binary_node *le = nullptr, Binary_node *ri = nullptr) :val(v

二叉树的前序建立,前中后序遍历的非递归算法

二叉树的前序建立递归算法以及前中后序遍历的递归算法已经是人尽皆知了,递归算法也确实为代码的编写带来了很大的方便.然而,有时我们也确实需要它们的非递归算法.将递归算法转化为非递归算法可以帮助我们深入了解函数的调用与栈的原理.这里总结一下二叉树的这些重要的非递归算法. 一.前序建树 前序建树的基本思路是,接收用户输入的一组字符串,其中'#'代表空树,其他代表树结点的数据域值.例如,要建立如下一棵树 需要输入"AB#D##C##". 而非递归的思路是,1.设一个标志位来判断当前创建的结点是左

非递归前中后序遍历二叉树

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 写在前面: 最近准备找工作,捡起原来学习过的各种知识,加上一些自己的理解,梳理一下流程,巩固自己的认识,一步两步,一步两步... ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 二叉树的遍历是树操作的基础,一般的前中后序递归遍历比较简单,这里就不列出了,主要是非递归实

【算法导论】二叉树的前中后序非递归遍历实现

二叉树的递归遍历实现起来比较简单,而且代码简洁:而非递归遍历则不那么简单,我们需要利用另一种数据结构---栈来实现.二叉树的遍历又可以分为前序.中序和后序三种,它们是按照根结点在遍历时的位置划分的,前序遍历则根结点先被遍历,中序则根结点在左右叶子节点之间被遍历,后序则是根结点最后被遍历.三种非递归遍历中,前序和中序都不是太复制,而后序遍历则相对较难. 一.前序遍历 我们这里前序遍历按照"根-左-右"的顺序来遍历.这里按照"递归--非递归"的次序来研究,之后的几种亦是

【数据结构】 非递归前中后序遍历二叉树

数据结构学的递归了,深入了解后写一个三序非递归的版本. //测试数据:abd##eg##h##c#f## #include <cstdio> #include <iostream> typedef char ElemType; typedef struct Node { ElemType elem; struct Node *lchild,*rchild; }Node,*BiTree; typedef struct{ BiTree *base; BiTree *top; int s

二叉树系列 - 二叉树的前/中/后序遍历(非递归)

二叉树的遍历是二叉树中最最基础的部分. 这里整理二叉树不用递归实现三种顺序遍历的方式. 不用递归的话,一般需要栈来完成.当然线索二叉树(不需要栈或递归)也可以完成中序遍历,这种方式在这篇文章中已经讨论过.这里着重讨论使用栈的实现方式. 中序遍历 (1) 双while,第二个内层while是为了不断压入left child. vector<int> inorderTraversal(TreeNode *root) { vector<int> v; if(!root) return v

POJ 2255 Tree Recovery &amp;&amp; Ulm Local 1997 Tree Recovery (二叉树的前中后序遍历)

链接:poj.org/problem?id=2255 题意: 分别给你一个二叉树的前序遍历序列和中序遍历序列,让你给出这个二叉树的后序遍历序列. 思路: 对于二叉树的三种遍历方式,都可以使用递归来实现,那么也一定可以使用递归来拆解,以达到从遍历序列确定二叉树具体结构的目的.对于前序遍历来说,第一个字母一定是根,并且在序列中根的左子树包含的点一定出现在根的右子树的前面.对于中序遍历序列来说,根前面出现的字母所代表的点一定出现在左子树中,根后面出现的字母所代表的点一定出现在右子树中.在根据前序与中序

二叉树的前中后序遍历

#include<stdio.h> #include<string.h> #include<stdlib.h> #define Size 100 #define Resize 10 typedef struct Bitnode{ //定义结点 char data; struct Bitnode *lchild,*rchild; }Bitnode,*Bitree; typedef struct Stack{ //定义栈 Bitree *base; int top; int