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

来源:互联网 发布:淘宝回收手机安全吗 编辑:程序博客网 时间:2024/05/16 19:12

这个学期一直在忙着准备面试,复习,都没有看新的书,也很久没有写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 0
原创粉丝点击