劍指offer程式碼解析——面試題25二叉樹中和為某一值的路徑
阿新 • • 發佈:2022-05-03
題目:輸入一棵二叉樹和一個整數,打印出二叉樹中結點值的和為輸入整數的所有路徑。PS:從根結點開始,一直到葉子結點形式一條路徑。
分析:要找出路徑之和為指定整數的路徑,就需要遍歷二叉樹的所有路徑。此外,由於路徑是指根結點到葉子結點的線段,因此我們想到採用深度優先的方式遍歷二叉樹。深度優先演算法又分為:先序遍歷、中序遍歷、後序遍歷,其中先序遍歷符合我們的要求。
首先需要建立一個棧,用來儲存當前路徑的結點。採用先序遍歷演算法遍歷結點時,先將途中經過的結點均存入棧中,然後判斷當前結點是否為葉子結點,若不是葉子結點的話,則遞迴遍歷該結點的左孩子和右孩子;若是葉子結點的話,計算下當前棧中所有結點之和是否為指定的整數,若是的話列印棧中所有元素。然後這個函式在返回之前,將當前葉子結點從棧中刪除。程式碼如下:
/** * 題目:輸入一棵二叉樹和一個整數,打印出二叉樹中結點值的和為輸入整數的所有路徑。 * PS:從根結點開始,一直到葉子結點形式一條路徑。 * @author 大閒人柴毛毛 * @date 2016年3月15日 */ public class PrintBinaryPath { /** * 分析:要找出路徑之和為指定整數的路徑,就需要遍歷二叉樹的所有路徑。 * 此外,由於路徑是指根結點到葉子結點的線段,因此我們想到採用深度優先的方式遍歷二叉樹。 * 深度優先演算法又分為:先序遍歷、中序遍歷、後序遍歷,其中先序遍歷符合我們的要求。 */ /** * 首先需要建立一個棧,用來儲存當前路徑的結點。 * 採用先序遍歷演算法遍歷結點時,先將途中經過的結點均存入棧中,然後判斷當前結點是否為葉子結點,若不是葉子結點的話,則遞迴遍歷該結點的左孩子和右孩子; * 若是葉子結點的話,計算下當前棧中所有結點之和是否為指定的整數,若是的話列印棧中所有元素。 * 然後這個函式在返回之前,將當前葉子結點從棧中刪除。 */ /** * 列印二叉樹中路徑之和為n的路徑 * @param root 二叉樹 * @param n 路徑之和 * @return 返回函式能否正確執行 */ public static boolean printBinaryPath(BinaryTreeNode<Integer> root,int n){ //樹為空 if(root==null){ System.out.println("樹為空!"); return false; } //n小於0 if(n<=0){ System.out.println("n小於等於0!"); return false; } //建立棧 Stack<Integer> stack = new Stack<Integer>(); //開始遞迴查詢路徑 printBinaryPath(root,n,stack); return true; } /** * 遞迴尋找路徑之和為n的路徑 * @param root 二叉樹根結點 * @param n 指定整數 * @param stack 用於儲存當前路徑的棧 */ private static void printBinaryPath(BinaryTreeNode<Integer> root, int n, Stack<Integer> stack) { //若當前根結點為葉子結點 if(root.left==null && root.right==null){ //將葉子結點入棧 stack.add(root.data); //計算當前路徑之和 int sum = 0; Iterator<Integer> it = stack.iterator(); while(it.hasNext()) sum += it.next(); //若當前路徑之和==n,則列印這條路徑 if(sum==n){ Iterator<Integer> it2 = stack.iterator(); while(it2.hasNext()) System.out.print(it2.next()+","); System.out.println("n-------------------"); } //將當前葉子結點出棧 stack.pop(); //返回上層結點 return; } //若當前結點為非葉子結點 else{ //將根結點入棧 stack.add(root.data); //若左孩子存在,遞迴左孩子 if(root.left!=null) printBinaryPath(root.left,n,stack); //若右孩子存在,遞迴右孩子 if(root.right!=null) printBinaryPath(root.right,n,stack); //將當前葉子結點出棧 stack.pop(); //返回上層結點 return; } } /** * 測試 */ public static void main(String[] args){ //構建二叉樹 BinaryTreeNode<Integer> node1 = new BinaryTreeNode<Integer>(); BinaryTreeNode<Integer> node2 = new BinaryTreeNode<Integer>(); BinaryTreeNode<Integer> node3 = new BinaryTreeNode<Integer>(); BinaryTreeNode<Integer> node4 = new BinaryTreeNode<Integer>(); BinaryTreeNode<Integer> node5 = new BinaryTreeNode<Integer>(); node1.data = 10; node2.data = 5; node3.data = 12; node4.data = 4; node5.data = 7; node1.left = node2; node1.right = node3; node2.left = node4; node2.right = node5; printBinaryPath(node1,19); } } /** * 二叉樹的結點 */ class BinaryTreeNode<T>{ T data;//結點的資料域 BinaryTreeNode<T> left;//左子樹 BinaryTreeNode<T> right;//右子樹 }