二叉树之非递归遍历-创新互联

1、二叉树的遍历

成都创新互联公司是一家专业提供龙南企业网站建设,专注与成都网站建设、网站设计、html5、小程序制作等业务。10年已为龙南众多企业、政府机构等服务。创新互联专业的建站公司优惠进行中。

 为什么要有遍历操作:将线性结构-------->非线性结构;

     将递归程序-------->非递归程序;

2、二叉树的三种递归遍历:

 先序遍历:先访问根(父)结点,在访问左分支,最后访问右分支;

 中序遍历:先访问左分支,在根结点,最后右分支;

 后序遍历:先访问左分支,在访问右分支,最后访问根节点;

二叉树之非递归遍历

所有程序皆正确测试过,后面将给完整程序和测试程序,测试结果。

以下就是递归遍历,先序,中序,后序:

下面的都是在类外定义的函数,所以为模板函数:

//先序遍历
template
void BinTree::prevOrder(BinTreeNode *t)const{
    if(t == NULL){
        return;
    }else{
        cout<data<<" ";
        prevOrder(t->leftChild);
        prevOrder(t->rightChild);
    }
}
//中序遍历
template
void BinTree::inOrder(BinTreeNode *t)const{
    if(t == NULL){
        return;
    }else{
        inOrder(t->leftChild);
        cout<data<<" ";
        inOrder(t->rightChild);
    }
}
//后序遍历
template
void BinTree::endOrder(BinTreeNode *t)const{
    if(t == NULL){
        return;
    }else{
        endOrder(t->leftChild);
        endOrder(t->rightChild);
        cout<data<<" ";
    }
}

3、二叉树的4种非递归遍历

 (1)、深度优先用栈

 先序的非递归遍历:栈先入后出,根结点入栈,栈不空,出栈访问,此时将右孩子入栈,在将左孩子入栈,栈不空,出栈访问,就是循环了;

 代码如下:

template
void BinTree::prevOrder_1(BinTreeNode* t)const{
    stack *> st;  //栈里面放的是指向节点的指针
    BinTreeNode *tmp;

    if(t != NULL){   //根不为空
        st.push(t);  //根入栈
        while(!st.empty()){  //栈非空
            tmp = st.top();  //读栈顶元素
            st.pop();        //出栈
            cout<data<<" ";  //访问
            if(tmp->rightChild){    //右孩子存在
                st.push(tmp->rightChild);  //入栈
            }
            if(tmp->leftChild){     //左孩子存在
                st.push(tmp->leftChild);  //入栈
            }
        }
    }
}

 中序的非递归遍历:就是先把根及左分支一直压栈,栈不空,出栈访问,再看右孩子,有的话,压栈,结束条件想清楚就行。

 代码如下:

template
void BinTree::inOrder_1(BinTreeNode* t)const{
    stack *> st;  //栈里面放的是指向节点的指针
    BinTreeNode *p = t;
                     //用的是do while()循环
    do{
        while(p != NULL){  //将根和左子树一直入栈
            st.push(p);
            p = p->leftChild;
        }
        if(!st.empty()){  //栈不空,
            p = st.top();  //读栈顶元素
            st.pop();      //出栈
            cout<data<<" ";  //访问
            p = p->rightChild;   //此时往刚才栈顶元素的右孩子走;
        }             //中序遍历时,当root出栈时,此时栈空,没有p!=NULL的话,将出错。
    }while(p != NULL || !st.empty()); //为根的时候右边还要入栈。
}

 后序的非递归遍历:思想就是要有一个标志,当为右边回来的时候才能访问根节点!!!

 代码如下:

typedef enum{L, R}Tag;   //枚举定义新的类型
template  //定义一个类,为的是做标志
class stkNode{
public:
    stkNode(BinTreeNode *p = NULL) : ptr(p), tag(L){}
public:                  //数据成员为公有,便于访问
    BinTreeNode *ptr;  
    Tag                   tag; //L R
};
template
void BinTree::endOrder_1(BinTreeNode* t)const{
    stkNode n;
    stack> st;  //此时栈中存放的是对象!
    BinTreeNode *p = t;
    
    do{
        while(p != NULL){  //不为空,一路向左入栈
            n.ptr = p;    //将指针给过去
            n.tar = L;    //记为左边入栈
            st.push(n);
            p = p->leftChild;
        }
        bool isRun = true;  //是否继续的标志
        while(isRun && !st.empty()){  
            n = st.top();  //读栈顶
            st.pop();     //出栈

            switch(n.tag){  //根据L和R选择
            case L:
                p = n.ptr; 
                n.tag = R;  //更改为R
                st.push(n);  //压入栈
                p = p->rightChild;  //看有没有右孩子,有的话,结束循环,要入栈的;
                isRun = false;  //特别重要,保证了右孩子的入栈!
                break;
            case R:
                cout<data<<" ";
                break;
            }
        }
    }while(!st.empty());//不用p1=NULL,因为当栈空时,最后一个节点刚好被访问完成。
}

画图跟踪后序如下:

二叉树之非递归遍历

 (2)、广度优先用队列

 层次遍历:根结点入队列,队列非空,出队访问,在将左右孩子入队,非空,访问,构成循环;

 代码如下:

template
void BinTree::levelOrder(BinTreeNode* t)const{
    queue *> qu;  //队列里面放的是指向节点的指针
    BinTreeNode *p;

    if(t != NULL){ //根非空
        qu.push(t);  //根入队
        while(!qu.empty()){  //队列非空
            p = qu.front();  //读队首
            qu.pop();        //出队
            cout<data<<" "; //访问
            if(p->leftChild){  //左孩子存在
                qu.push(p->leftChild); //入队
            }
            if(p->rightChild){   //右孩子存在
                qu.push(p->rightChild);  //入队
            }
        }
    }
}

另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


当前名称:二叉树之非递归遍历-创新互联
文章来源:http://ybzwz.com/article/ccijoh.html