美文网首页
[C++] 非递归实现前中后序遍历二叉树

[C++] 非递归实现前中后序遍历二叉树

作者: winng伍寅 | 来源:发表于2019-06-03 16:24 被阅读0次

网上代码一搜一大片,大同小异咯。
书上的函数实现代码甚至更胜一筹,而且抄一遍就能用,唯一问题是没有写二叉树节点和树的模版类的构造实现,和没有具体实现 visit 函数(也没说明,略坑)。

只需要前中后序遍历的话很多函数都不需要,此外值得吐槽的一点是,明明 BinaryTreeNode 类里面接口写的很明确,私有成员也都保护起来了,最后却把 BinaryTree 添加为了友元类,这波操作着实令人费解。
为了添加这个友元类还需要先进行两个类的声明,之后才能逐个实现,迷了。
但这都不是我按顺序实现了接口函数,最后还是没有调用接口函数的理由。所以根本原因其实就是懒。

前置技能

四种遍历方法分别为:

  • 层次遍历 “ 从上到下,从左到右 ”
  • 前序遍历 “ 根结点 -> 左子树 -> 右子树 ”
  • 中序遍历 “ 左子树 -> 根结点 -> 右子树 ”
  • 后序遍历 “ 左子树 -> 右子树 -> 根结点 ”
图片来自网络

层次遍历使用了队列进行实现,而前中后序遍历是利用的栈来实现。而前序遍历、中序遍历和后序遍历中,后序遍历的实现无疑是最复杂的。

需求描述

直接上头文件,需要注意的是我没有实现建树、删树和插入的函数,顺手还多抄了一个层次遍历的函数。整体来看是一个很菜的代码,只在主函数里随便构了一个二叉树测试遍历函数。
全部都是模版类的实现写起来很麻烦,实现好了很舒服23333
binarytree.h


template<class T>
class BinaryTreeNode;

template<class T>
class BinaryTree;

template<class T>
class BinaryTreeNode{
private:
    T element;                        //数据域
    BinaryTreeNode<T> * leftChild;    //左孩子
    BinaryTreeNode<T> * rightChild;   //右孩子
public:
    BinaryTreeNode();                 //默认构造
    BinaryTreeNode(T& ele);           //给定数据域值的构造
    BinaryTreeNode(T& ele, BinaryTreeNode<T> * l, BinaryTreeNode<T> * r);
    BinaryTreeNode<T> * getLeftChild();           //返回左孩子
    BinaryTreeNode<T> * getRightChild();          //返回右孩子
    bool setLeftChild(BinaryTreeNode<T> * l);     //设置左孩子
    bool setRightChild(BinaryTreeNode<T> * r);    //设置右孩子
    T getValue() const;                           //返回数据值
    bool isLeaf() const;                          //判断是否为叶子节点
    friend class BinaryTree<T>;
};

template<class T>
class BinaryTree{
private:
    BinaryTreeNode<T> * root;  //根节点
public:
    BinaryTree();              //默认构造
    BinaryTree(BinaryTreeNode<T> * r);
    ~BinaryTree();             //析构
    bool isEmpty() const;      //判断是否为空树
    void visit(BinaryTreeNode<T> * pointer);
    BinaryTreeNode<T> * getRoot() const;              //返回根节点
    void preOrder(BinaryTreeNode<T> * root);          //先序遍历
    void inOrder(BinaryTreeNode<T> * root);           //中序遍历
    void postOrder(BinaryTreeNode<T> * root);         //后序遍历
    void levelOrder(BinaryTreeNode<T> * root);        //层次遍历
};

具体实现

binarytree.cpp

#include"binarytree.h"
#include<iostream>
#include<queue>
#include<stack>

template<class T>
BinaryTreeNode<T>::BinaryTreeNode(){
    element = 0;
    leftChild = nullptr;
    rightChild = nullptr;
}

template<class T>
BinaryTreeNode<T>::BinaryTreeNode(T& ele){
    element = ele;
    leftChild = nullptr;
    rightChild = nullptr;
}
template<class T>
BinaryTreeNode<T>::BinaryTreeNode(T& ele, BinaryTreeNode<T> * l, 
                                  BinaryTreeNode<T> * r){
    element = ele;
    leftChild = l;
    rightChild = r;
}

template<class T>
BinaryTreeNode<T> * BinaryTreeNode<T>::getLeftChild(){
    return leftChild;
}

template<class T>
BinaryTreeNode<T> * BinaryTreeNode<T>::getRightChild(){
    return rightChild;
}

template<class T>
T BinaryTreeNode<T>::getValue() const{
    return element;
}

template<class T>
bool BinaryTreeNode<T>::setLeftChild(BinaryTreeNode<T> * l){
    if(leftChild == nullptr){
        leftChild = l;
        return true;
    }
    else return false;
}

template<class T>
bool BinaryTreeNode<T>::setRightChild(BinaryTreeNode<T> * r){
    if(rightChild == nullptr){
        rightChild = r;
        return true;
    }
    else return false;
}

template<class T>
bool BinaryTreeNode<T>::isLeaf() const{
    if(leftChild == nullptr && rightChild == nullptr)
        return true;
    else return false;
}

template<class T>
BinaryTree<T>::BinaryTree(){
    root = nullptr;
}

template<class T>
BinaryTree<T>::BinaryTree(BinaryTreeNode<T> * r){
    root = r;
}

template<class T> 
BinaryTree<T>::~BinaryTree(){
    root = nullptr;
}

template<class T>
bool BinaryTree<T>::isEmpty() const{
    if (root == nullptr)    return true;
    else return false;
}

template<class T>
BinaryTreeNode<T> * BinaryTree<T>::getRoot() const{
    return root;
}

template<class T>
void BinaryTree<T>::visit(BinaryTreeNode<T> * pointer){
    std::cout<<pointer->element<<std::endl;
}

template<class T>
void BinaryTree<T>::preOrder(BinaryTreeNode<T> * root){
    using std::stack;
    stack<BinaryTreeNode<T> * > nodeStack;
    BinaryTreeNode<T> * pointer = root;
    while(!nodeStack.empty()||pointer != nullptr){
        if(pointer != nullptr){
            visit(pointer);
            if(pointer -> rightChild !=  nullptr)
                nodeStack.push(pointer->rightChild);
            pointer = pointer->leftChild;
        }
        else{
            pointer = nodeStack.top();
            nodeStack.pop();
        }
    }
}

template<class T>
void BinaryTree<T>::inOrder(BinaryTreeNode<T> * root){
    using std::stack;
    stack<BinaryTreeNode<T> * > nodeStack;
    BinaryTreeNode<T> * pointer = root;
    while(!nodeStack.empty()||pointer){
        if(pointer){
            nodeStack.push(pointer);
            pointer = pointer -> leftChild;
        }
        else{
            pointer = nodeStack.top();
            visit(pointer);
            pointer = pointer -> rightChild;
            nodeStack.pop();
        }
    }
}

template<class T>
void BinaryTree<T>::postOrder(BinaryTreeNode<T> * root){
    using std::stack;
    stack<BinaryTreeNode<T> * > nodeStack;
    BinaryTreeNode<T> * pointer = root;
    BinaryTreeNode<T> * pre = root;
    while(pointer != nullptr){
        while(pointer -> leftChild != nullptr){
            nodeStack.push(pointer);
            pointer = pointer -> leftChild;
        }
        while(pointer != nullptr && (pointer -> rightChild == nullptr ||
                                     pre == pointer->rightChild)){
            visit(pointer);
            pre = pointer;
            pointer = nodeStack.top();
            nodeStack.pop();
        }
        nodeStack.push(pointer);
        pointer = pointer -> rightChild;
    }
}

template<class T>
void BinaryTree<T>::levelOrder(BinaryTreeNode<T> * root){
    using std::queue;
    queue<BinaryTreeNode<T> *>nodeQueue;
    BinaryTreeNode<T> * pointer = root;
    if(pointer)
        nodeQueue.push(pointer);
    while(!nodeQueue.empty()){
        pointer = nodeQueue.front();
        visit(pointer);
        nodeQueue.pop();
        if(pointer->leftChild)  nodeQueue.push(pointer->leftChild);
        if(pointer->rightChild) nodeQueue.push(pointer->rightChild);
    }
}

main.cpp

#include"binarytree.h"
#include <iostream>

using namespace std;

int main(){
    int a1,a2,a3,a4,a5;
    cin>>a1>>a2>>a3>>a4>>a5;
    BinaryTreeNode<int> n1(a1),n2(a2),n3(a3),n4(a4),n5(a5);
    BinaryTree<int> t(&n1);
    n1.setLeftChild(&n2);
    n1.setRightChild(&n3);
    n2.setLeftChild(&n4);
    n2.setRightChild(&n5);          //真·随便接的
    cout<<"层次遍历:"<<endl;
    t.levelOrder(&n1);
    cout<<"前序遍历:"<<endl;
    t.preOrder(&n1);
    cout<<"中序遍历:"<<endl;
    t.inOrder(&n1);
    cout<<"后序遍历:"<<endl;
    t.postOrder(&n1);
    return 0;
}

相关文章

  • 算法之二叉树

    二叉树之C++实现 创建二叉树 复制二叉树 先序遍历 递归实现 非递归实现 中序遍历 递归实现 非递归实现 后序遍...

  • 各种二叉树遍历

    C++实现,二叉树的递归、非递归版本的前序、中序、后序遍历。

  • 左神算法笔记——Morris遍历

    基本问题——实现二叉树的前序、中序、后序遍历 (递归、非递归,mirros方法) 递归 递归方式下的前中后遍历 非...

  • 二叉树的操作

    /*主要内容:1、实现二叉树的先序、中序、后序遍历,包括递归方式和非递归方式*/ 实现二叉树的先序、中序、后序遍历...

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

    goLang 二叉树遍历(递归 非递归 前序遍历 中序遍历 后序遍历 层序遍历) 前序遍历 中序遍历 后序遍历 代...

  • 二叉树,非递归法

    递归法 二叉树的递归,有前序遍历、中序遍历、后序遍历,一般采用递归法,比较简单 非递归法 二叉树非递归法,采用栈来实现

  • 数据结构-树的遍历

    1. 先序遍历 递归实现 非递归实现 2. 中序遍历 递归实现 非递归实现 3. 后序遍历 递归实现 非递归实现 ...

  • Java二叉树的遍历

    Java二叉树的遍历 利用递归和非递归实现二叉树的先序,中序,后序遍历以及使用队列实现二叉树的层次遍历

  • 二叉树前、中、后序遍历、层次遍历

    1、前序遍历 非递归:利用Stack实现 递归 2、中序遍历 非递归:利用Stack实现 递归: 3、后序遍历 非...

  • 二叉树三种遍历的递归和非递归实现&层次遍历实现(C++)

    对于二叉树的三种遍历方式(先序、中序、后序),用递归和非递归(栈)的方式实现,对于后序遍历用队列实现。 四种遍历方...

网友评论

      本文标题:[C++] 非递归实现前中后序遍历二叉树

      本文链接:https://www.haomeiwen.com/subject/wyscxctx.html