二叉树遍历的非递归实现

本文和该篇文章 leetcode | 二叉树的前序遍历、中序遍历、后续遍历的非递归实现有不同的实现方式,此文章的非递归遍历实现算法,易于理解和实现。

包含插入、遍历、统计树中节点的个数、统计树的深度等操作。
遍历操作包含:
- 迭代(非递归)实现的前序、中序、后序、层序遍历。

其中前序和中序,一个是先访问在入栈、一个是先入栈后访问有极大的相似性;
其中后序遍历使用了双栈操作,使思想简化易于实现;
其中层序遍历采用FIFO**队列**实现;

以下源码,采用c++实现


#include <stack>
#include <queue>
#include <algorithm>
#include <iostream>
using namespace std;

template<class T>
class Node {
public:
    T item;
    Node* left;
    Node* right;
};

template<class T>
class BinaryTree {
private:
    Node<T>* binary_tree;
    int items_index;

    // 用数组元素创建一棵树,以#作为分隔符结束当前子树的增长
    template<size_t size>
    Node<T>* Creat(Node<T>* tree, const T(&items)[size]) {
        T item = items[items_index++];
        if (item == '#') {
            tree = NULL;
        }
        else {
            tree = new Node<T>;
            tree->item = item;
            tree->left = Creat(tree->left, items);
            tree->right = Creat(tree->right, items);
        }
        return tree;
    }
    //递归计算tree所有节点的个数:左子树+右子树+1(1为当前根)
    int GetNodeNums(Node<T>* tree) {
        if (tree == NULL)
            return 0;
        return GetNodeNums(tree->left) + GetNodeNums(tree->right) + 1;
    }
    // 递归计算tree的深度:max(左子树、右子树) + 1 (1为当前根)
    int GetTreeDepth(Node<T>* tree) {
        if (tree == NULL)
            return 0;
        return max(GetTreeDepth(tree->left), GetTreeDepth(tree->right)) + 1;
    }
public:
   BinaryTree() {
    binary_tree = NULL;
    items_index = 0;
}
public:
    template<size_t size>
    void CreatTree(const T(&items)[size]) {
        binary_tree = Creat(binary_tree, items);
    };

    int size() {
        return GetNodeNums(binary_tree);
    }
    int depth() {
        return GetTreeDepth(binary_tree);
    }
    // 前序遍历:先访问根节点,再访问左、右节点
    //      先访问、后入栈
    //   如果tree非空:访问栈顶元素,把tree入栈,tree指向左子树
    //   如果tree 为空:说明已经到左子树的尽头,弹出当前栈顶元素tree指向右子树。
    void PreorderTravel() {
        cout << "PreorderTravel: ";
        if (binary_tree == NULL)
            return;
        stack<Node<T>*> stk;
        Node<T>* tree = binary_tree;
        while (tree || stk.empty() == false) {
            if (tree) {
                cout << tree->item << " ";
                stk.push(tree);
                tree = tree->left;
            }
            else {
                tree = stk.top();
                tree = tree->right;
                stk.pop();
            }
        }
        cout << endl;
    }
    // 中序遍历:先访问左,再根、最后右
    //   先入栈、后访问
    // 如果tree非空:把tree入栈,tree指向左子树
    // 如果tree为空:说明已经向左走到了尽头,弹出当前栈顶元素,访问tree,tree指向右子树
    void InorderTravel() {
        cout << "InorderTravel: ";
        if (binary_tree == NULL)
            return;
        stack<Node<T>*> stk;
        Node<T>* tree = binary_tree;
        while (tree || stk.empty() == false) {
            if (tree) {
                stk.push(tree);
                tree = tree->left;
            } else {
                tree = stk.top();
                stk.pop();
                cout << tree->item << " ";
                tree = tree->right;
            }
        }
        cout << endl;
    }
    // 后续遍历:先左、再右,最后根
    // 采用两个栈实现,先压入当前节点的左子树,然后压入右子树
    // 得到的顺序:根-右-左,刚好是后序遍历的逆序;在另一个栈反转
    void PostorderTravel() {
        cout << "PostorderTravel: ";
        if (binary_tree == NULL)
            return;
        Node<T>* tree = binary_tree;
        stack<Node<T>* > stk1, stk2;
        stk1.push(tree);
        while (stk1.empty() == false) {
            tree = stk1.top();
            stk1.pop();
            stk2.push(tree);
            if (tree->left)
                stk1.push(tree->left);
            if (tree->right)
                stk1.push(tree->right);
        }

        while (stk2.empty() == false) {
            cout << stk2.top()->item << " ";
            stk2.pop();
        }
        cout << endl;
    }
    // 层序遍历, 逐层从上到下从左到右访问
    // 采用队列实现,先入先出
    // 先把根入队列,当队列非空时,弹出队列最前的元素并访问,
    // 如果左右子树非空则依次入队列
    void LevelorderTravel() {
        cout << "LevelorderTravel: ";
        if (binary_tree == NULL)
            return;
        Node<T>* tree = binary_tree;
        queue<Node<T>* > que;
        que.push(tree);
        while (que.empty() == false) {
            tree = que.front();
            que.pop();
            cout << tree->item << " ";
            if (tree->left)
                que.push(tree->left);
            if (tree->right)
                que.push(tree->right);
        }
        cout << endl;
    }


};

int main()
{

/*
           A
      B         C
    D   E     F    G
  H         I       J
    K

*/
    const char str[] = "ABDH#K###E##CFI###G#J##";
    BinaryTree<char> btree;
    btree.CreatTree(str);
    cout << "Tree size: " << btree.size() << endl;
    cout << "Tree Depth: " << btree.depth() << endl;
    btree.PreorderTravel();
    btree.InorderTravel();
    btree.PostorderTravel();
    btree.LevelorderTravel();
    return 0;
}

创建树的结构如下:

           A
      B         C
    D   E     F    G
  H         I       J
    K

输出结果如下:

Tree size: 11
Tree Depth: 5
PreorderTravel: A B D H K E C F I G J 
InorderTravel: H K D B E A I F C G J 
PostorderTravel: K H D E B I F J G C A 
LevelorderTravel: A B C D E F G H I J K 
[Finished in 0.7s]

参考资料:未知。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值