尋找二叉樹上從根結點到給定結點的路徑


一、遞歸實現

思想:借助棧結構來保存路徑上的結點,首先從根結點開始,一直往左找,如果左邊找到就返回true;否則,如果左邊找不到並且右子樹不為空的情況下再繼續往右子樹找。如果左右子樹都找不到,就彈出棧頂結點並返回false。方法運行完畢后,棧中保存的元素就是一條從根到給定結點的路徑。

public static boolean searchNode(TreeNode root,Stack<TreeNode> s,TreeNode node) {
        if(root == null) return false;
        s.push(root);
        if(root.val == node.val) return true;
        boolean b = false;
        //先去左子樹找
        if(root.left != null) b = searchNode(root.left,s,node);
        //左子樹找不到並且右子樹不為空的情況下才去找
        if(!b && root.right != null) b = searchNode(root.right,s,node);
        //左右都找不到,彈出棧頂元素
        if(!b) s.pop();
        return b;
    }

程序運行結束后,棧中保存的就是要求的路徑,參數root代表根節點,s代表棧,node代表給定的節點。如果不想用值來比較,就直接把if(root.val == node.val)換成if(root == node),道理都是一樣的。

二、非遞歸實現

思想:這個稍微有些復雜,當然也是要借助棧來完成。其實這里和二叉樹的非遞歸先序遍歷的思想差不多,只是在這個基礎上進行一些改造。首先,新建一個棧,保存根節點。然后開始一直向左查找,查找的過程中把結點入棧。如果在向左找的過程中遇到了給定的結點,那么就輸出並返回,這個過程比較好理解。關鍵是下面的彈棧的過程,如果在向左找的過程中遇到了null,說明當前棧頂元素的左子樹為null。那么我們向棧頂元素的右子樹開始查找。令p為棧頂元素,如果棧頂元素的右子樹為null,那么彈出棧頂元素,並用pre來保存剛彈出的元素,之所以設置pre,是因為如果當前棧頂元素的右子樹不為null的時候,不能輕易彈出,首先得去右子樹上去查找,如果右孩子被彈出了,說明右子樹上肯定沒有,那么當前結點才可以彈出。

public static void searchNode(TreeNode root,TreeNode node) {
        if(root == null || node == null) return;
        Stack<TreeNode> s = new Stack<>();
        TreeNode p = root;
        TreeNode pre = null; //上一次出棧的結點
        while(p != null || !s.isEmpty()) {
            while(p != null) {
                //這個while循環的思想還是一直往左找,找的過程結點入棧,如果找到了就打印輸出並返回。
                s.push(p);
                if(p.val == node.val) {
                    for (TreeNode treeNode : s) {
                        System.out.print(treeNode.val + " ");
                    }
                    return;
                }
                p = p.left;
            }
            //走到這一步說明棧頂元素的左子樹為null,那么就開始往棧頂元素的右子樹上去找。
            if(!s.isEmpty()) {
                p = s.peek();
                //如果棧頂元素的右子樹為null,或者右子樹被遍歷過,則彈棧。
                while(p.right == null || pre != null && p.right == pre) {
                    pre = s.pop();
                    p = s.peek();
                }
                //繼續遍歷p的右子樹
                p = p.right;
            }
        }
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM