文章目錄
樹是一種常見的數據結構,由一系列節點和節點之間的關係組成。樹的搜索和遍歷是筆試和麪試經常考的。最基本的樹——二叉樹,顧名思義,父節點最多隻有兩個子節點。我們先創建一個樹節點類:
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
樹的搜索
深度優先搜索(Deep First Search)
深度優先搜索可以採用遞歸實現,代碼如下:
List<Integer> visitList = new ArrayList();
public void dfs(TreeNode root){
if(root==null) return;
visitList.add(root.val);
dfs(root.left);
dfs(root.right);
}
當然,也可以非遞歸的方式,不過此時要藉助棧來實現:
public void dfs(TreeNode root){
if(root==null){
return;
}
Stack<TreeNode > stack = new Stack<TreeNode >();
stack.push(node);
while(!stack.isEmpty()){
TreeNode rnode = stack.pop();
visitlist.add(rnode.val);
if(rnode.right!=null){
stack.push(rnode.right);
}
if(rnode.left!=null){
stack.push(rnode.left);
}
}
}
廣度優先搜索(Breadth First Search)
廣度優先搜索藉助隊列的FIFO特性實現,大致思路是:先搜索當前層的節點,然後將左子樹和右子樹添加到隊列中,其Java代碼如下(假設按層輸出):
public List<List<Integer>> levelOrderBottom(TreeNode root) {
List<List<Integer>> res = new ArrayList();
Queue<TreeNode> queue = new LinkedList();
queue.add(root); //向隊列中添加根節點
if(root==null) return res;
while(!queue.isEmpty()){
List<Integer> list = new ArrayList();
Queue<TreeNode> temp = new LinkedList();
while (!queue.isEmpty()) {
TreeNode n = queue.remove();
list.add(n.val);
if (n.left != null)
temp.add(n.left);
if (n.right != null)
temp.add(n.right);
}
queue = temp;
res.add(list);
}
return res;
}
樹的遍歷
數的遍歷方式可以按照父節點、左子節點、右子節點的訪問順序不同分爲以下三種:前序遍歷,中序遍歷,後序遍歷。
前序遍歷(PreOrder)
先訪問父節點,再訪問左子節點,最後訪問右子節點。那麼對於上面那張圖對應的二叉樹的遍歷順序依次爲:1,2,4,5,3,6,7。可以發現,樹的深度度優先搜索訪問順序和前序遍歷是一樣的。對應的Java代碼如下:
List<Integer> visitList = new ArrayList();
public void preOrder(TreeNode root){
if(root==null) return;
visitList.add(root.val);
preOrder(root.left);
preOrder(root.right);
}
中序遍歷(InOrder)
先訪問左子節點,再訪問父節點,最後訪問右子節點。那麼對於上面那張圖對應的二叉樹的遍歷順序依次爲:4,2,5,1,6,3,7。對應的Java代碼如下:
List<Integer> visitList = new ArrayList();
public void inOrder(TreeNode root){
if(root==null) return;
inOrder(root.left);
visitList.add(root.val);
inOrder(root.right);
}
後序遍歷(PostOrder)
先訪問左子節點,再訪問右子節點,最後訪問父節點。那麼對於上面那張圖對應的二叉樹的遍歷順序依次爲:4,5,2,6,7,3,1。對應的Java代碼如下:
List<Integer> visitList = new ArrayList();
public void postOrder(TreeNode root){
if(root==null) return;
postOrder(root.left);
postOrder(root.right);
visitList.add(root.val);
}
不難發現,其實添加元素的位置的不同就對應了不同的遍歷方式。