二叉樹的遍歷

前序

// 遞歸
public void preOrderTraverse(TreeNode root) {  
        if (root != null) {  
            System.out.print(root.val+"  ");  
            preOrderTraverse1(root.left);  
            preOrderTraverse1(root.right);  
        }  
    }  

// 非遞歸
public void preOrderTraverse(TreeNode root) {  
        LinkedList<TreeNode> stack = new LinkedList<>();  
        TreeNode pNode = root;  
        while (pNode != null || !stack.isEmpty()) {  
            if (pNode != null) {  
                System.out.print(pNode.val+"  ");  
                stack.push(pNode);  
                pNode = pNode.left;  
            } else { 
                TreeNode node = stack.pop();  
                pNode = node.right;  
            }  
        }  
    }  

中序

public void inOrderTraverse(TreeNode root) {  
        LinkedList<TreeNode> stack = new LinkedList<>();  
        TreeNode pNode = root;  
        while (pNode != null || !stack.isEmpty()) {  
            if (pNode != null) {  
                stack.push(pNode);  
                pNode = pNode.left;  
            } else { //pNode == null && !stack.isEmpty()  
                TreeNode node = stack.pop();  
                System.out.print(node.val+"  ");  
                pNode = node.right;  
            }  
        }  
    }  

后序

兩種策略

  1. 對于任一結(jié)點(diǎn)P,將其入棧,然后沿其左子樹一直往下搜索。直到搜索到?jīng)]有左孩子的結(jié)點(diǎn),此時該結(jié)點(diǎn)出如今棧頂,可是此時不能將其出棧并訪問,因此其右孩子還為被訪問。
void postOrder3(BinTree *root)     //非遞歸后序遍歷
{
    stack<BinTree*> s;
    BinTree *cur;                      //當(dāng)前結(jié)點(diǎn) 
    BinTree *pre=NULL;                 //前一次訪問的結(jié)點(diǎn) 
    s.push(root);
    while(!s.empty())
    {
        cur=s.top();
        if((cur->lchild==NULL&&cur->rchild==NULL)||
           (pre!=NULL&&(pre==cur->lchild||pre==cur->rchild)))
        {
            cout<<cur->data<<" ";  //假設(shè)當(dāng)前結(jié)點(diǎn)沒有孩子結(jié)點(diǎn)或者孩子節(jié)點(diǎn)都已被訪問過 
              s.pop();
            pre=cur; 
        }
        else
        {
            if(cur->rchild!=NULL)
                s.push(cur->rchild);
            if(cur->lchild!=NULL)    
                s.push(cur->lchild);
        }
    }    
}
  1. 要保證根結(jié)點(diǎn)在左孩子和右孩子訪問之后才干訪問,因此對于任一結(jié)點(diǎn)P。先將其入棧。假設(shè)P不存在左孩子和右孩子。則能夠直接訪問它;或者P存在左孩子或者右孩子。可是其左孩子和右孩子都已被訪問過了。則相同能夠直接訪問該結(jié)點(diǎn)。若非上述兩種情況。則將P的右孩子和左孩子依次入棧。這樣就保證了每次取棧頂元素的時候,左孩子在右孩子前面被訪問。左孩子和右孩子都在根結(jié)點(diǎn)前面被訪問。
void postOrder2(BinTree *root)    //非遞歸后序遍歷
{
    stack<BTNode*> s;
    BinTree *p=root;
    BTNode *temp;
    while(p!=NULL||!s.empty())
    {
        while(p!=NULL)              //沿左子樹一直往下搜索。直至出現(xiàn)沒有左子樹的結(jié)點(diǎn) 
        {
            BTNode *btn=(BTNode *)malloc(sizeof(BTNode));
            btn->btnode=p;
            btn->isFirst=true;
            s.push(btn);
            p=p->lchild;
        }
        if(!s.empty())
        {
            temp=s.top();
            s.pop();
            if(temp->isFirst==true)     //表示是第一次出如今棧頂 
             {
                temp->isFirst=false;
                s.push(temp);
                p=temp->btnode->rchild;    
            }
            else                        //第二次出如今棧頂 
             {
                cout<<temp->btnode->data<<" ";
                p=NULL;
            }
        }
    }    
} 

廣度

public void levelTraverse(TreeNode root) {  
        if (root == null) {  
            return;  
        }  
        LinkedList<TreeNode> queue = new LinkedList<>();  
        queue.offer(root);  
        while (!queue.isEmpty()) {  
            TreeNode node = queue.poll();  
            System.out.print(node.val+"  ");  
            if (node.left != null) {  
                queue.offer(node.left);  
            }  
            if (node.right != null) {  
                queue.offer(node.right);  
            }  
        }  
    }  
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前中后序的遞歸實現(xiàn) 前中后序的非遞歸標(biāo)準(zhǔn)實現(xiàn) 總結(jié) 整體的思路是這樣的: 指針p指向root,創(chuàng)建棧 當(dāng)棧不為空或...
    熊白白閱讀 479評論 0 0
  • 遞歸實現(xiàn) 經(jīng)典的二叉樹三種遍歷方式,主要是區(qū)分先中后三種順序是怎樣的順序:“先中后”其實是描述根節(jié)點(diǎn)的位置順序。然...
    liaoliaoYU閱讀 1,801評論 0 3
  • 二叉樹的三種常用遍歷方式 學(xué)習(xí)過數(shù)據(jù)結(jié)構(gòu)的同學(xué)都清楚,除了層序遍歷外,二叉樹主要有三種遍歷方式: 1. 先序遍歷...
    SherlockBlaze閱讀 1,320評論 0 4
  • -先序遍歷: 訪問根結(jié)點(diǎn),先序遍歷其左子樹,先序遍歷其右子樹;運(yùn)用到遞歸void PreOrderTraversa...
    Spicy_Crayfish閱讀 2,129評論 0 0
  • 一、為什么前端需要學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法? 以前的前端頁面都是多頁面,現(xiàn)在前端的趨勢是單頁面應(yīng)用,需要將復(fù)雜的邏輯都放...
    Miss_麥兜閱讀 650評論 0 0

友情鏈接更多精彩內(nèi)容