二叉树的非递归先序、中序和后序遍历

这个学期一直在忙着准备面试,复习,都没有看新的书,也很久没有写Blog了。
之前写过二叉树的遍历,但是现在回去看实在是不忍直视,不仅写的复杂,而且还不一定正确。现在把二叉树的三种非递归遍历重写一遍。

二叉树的遍历是一个递归的过程,天然具备递归的属性,而非递归遍历的关键是栈的运用。其实任何一种递归算法都有一个对应的非递归算法。

先放上二叉树类的定义

class Tree {
public:
    Tree(char d) {
        leftChild = nullptr;
        rightChild = nullptr;
        data = d;
        tag = 0;
    }
    Tree() {
        leftChild = nullptr;
        rightChild = nullptr;
        tag = 0;//后序遍历标志位
    }
    void initTree(char* &str, Tree* &t);//使用字符串初始化二叉树,#表示空节点
    void fVisit();//先序遍历
    void mVisit();//中序遍历
    void bVisit();//后序遍历

private:
    Tree *leftChild;
    Tree *rightChild;
    char data;
    int tag;
};

树的初始化为了方便使用了递归算法,可以看出,树的递归算法是十分简洁优美的

void Tree::initTree(char* &str, Tree* &t){//先序构建二叉树
    if (*str != '#') {
        t = new Tree(*str);
        initTree(++str, t->leftChild);
        initTree(++str, t->rightChild);
    }
}

先序遍历:我认为是最简单的一种遍历

void Tree:: fVisit(){
    stack<Tree *> s;
    Tree *t = this;
    while (t != nullptr || !s.empty()) {
        if (t != nullptr) {
            cout << t->data << "\t";
            if (t->rightChild != nullptr) {
                s.push(t->rightChild);
            }
            t = t->leftChild;
        }else{
            t = s.top();
            s.pop();
        }
    }
}

中序遍历:和先序遍历类似

void Tree::mVisit(){
    stack<Tree *> s;
    Tree *t = this;
    while (t != nullptr || !s.empty()) {
        if (t != nullptr) {
            s.push(t);
            t = t->leftChild;
        }else {
            cout << s.top()->data << "\t";
            t = s.top()->rightChild;
            s.pop();
        }
    }
}

后序遍历:后序遍历比之前两种遍历方法稍稍复杂一些,主要是访问标志tag的引入。因为后序遍历节点入栈之后会被访问两次,第一次访问是进入其的右孩子,第二次访问才将其弹出,输出。所以我们在栈中第一次访问某个节点时将其tag置1。若访问的栈中元素tag值为1则将其弹出,并输出

void Tree::bVisit(){
    stack<Tree *> s;
    Tree *t = this;
    while (t != nullptr || !s.empty()) {
        if (t != nullptr) {
            s.push(t);
            t = t->leftChild;
        }else {
            if (s.top()->tag == 0) {
                t = s.top()->rightChild;
                s.top()->tag = 1;
            }else {
                cout << s.top()->data << "\t";
                s.pop();
            }
        }
    }
}

主函数调用

int main() {
    Tree *t = new Tree;
    char *str = "1378###6##59###";
    t->initTree(str, t);
    cout << "先序遍历" << endl;
    t->fVisit();
    cout << endl;
    cout << "中序遍历" << endl;
    t->mVisit();
    cout << endl;
    cout << "后序遍历" << endl;
    t->bVisit();
    cout << endl;
    system("pause");
    return 0;
}

输出结果

先序遍历
1       3       7       8       6       5       9
中序遍历
8       7       3       6       1       9       5
后序遍历
8       7       6       3       9       5       1

感觉还行。
最后希望我的同学—-将来的doctor们发达了不要忘了我

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值