二叉樹的遍歷-Java實現(遞歸、非遞歸)

二叉樹的遍歷

二叉樹的遍歷常分先序遍歷、中序遍歷、後序遍歷

  • 先序遍歷:先訪問根節點,再訪問左子節點,最後訪問右子節點
  • 中序遍歷:先訪問左子節點,再訪問跟節點,最後訪問右子節點
  • 後序遍歷:先訪問左子節點,再訪問右子節點,最好訪問根節點

實現的邏輯分爲遞歸、非遞歸的邏輯;

#TreeNode結構
public class TreeNode {
    public int val;
    public TreeNode left;
    public TreeNode right;

    public TreeNode(int x) {
        val = x;
    }
}
遞歸實現
public void visit(TreeNode node){
    System.out.print(node.val+" ");
}

/**
  * 遞歸先序遍歷
  **/
public void preOrderRecursion(TreeNode node){
  if(node==null) //如果結點爲空則返回
      return;
  visit(node);//訪問根節點
  preOrderRecursion(node.left);//訪問左孩子
  preOrderRecursion(node.right);//訪問右孩子
}

/**
  * 遞歸中序遍歷
  **/
public void preOrderRecursion(TreeNode node){
  if(node==null) //如果結點爲空則返回
      return;
  preOrderRecursion(node.left);//訪問左孩子
  visit(node);//訪問根節點
  preOrderRecursion(node.right);//訪問右孩子
}

/**
  * 遞歸後序遍歷
  **/
public void preOrderRecursion(TreeNode node){
  if(node==null) //如果結點爲空則返回
      return;
  preOrderRecursion(node.left);//訪問左孩子
  preOrderRecursion(node.right);//訪問右孩子
  visit(node);//訪問根節點
}
非遞歸實現:
  • 先序遍歷
    • 假設cur=head,將cur入棧
    • 不斷從棧中彈出棧頂節點,然後把右子節點和左子節點放入棧中
      (因爲先訪問左子節點,棧爲先進後出的數據結構,所以先放左子節點)
    • 當棧不爲空,不斷重複上一步驟
public List<Integer> preorderTraversal(TreeNode node) {
        List<Integer> rt = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        if (node == null) {
            return rt;
        }
        stack.push(node);
        while (!stack.empty()) {
            TreeNode curNode = stack.pop();
            rt.add(curNode.val);
            if (curNode.right != null) {
                stack.push(curNode.right);
            }
            if (curNode.left != null) {
                stack.push(curNode.left);
            }
        }
        return rt;
    }
  • 中序遍歷
    • 初始化cur=head
    • 將cur入棧,不斷將cur=cur.left(不斷取左子節點),重複當前過程
    • 如果cur爲空,則已經訪問到“最左“節點,出棧並打印當前節點的值,將其右子節點賦值給cur,重複上一步
public List<Integer> inorderTraversal(TreeNode node) {
        List<Integer> rt = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        if (node == null) {
            return rt;
        }
        while (!stack.empty() || node != null) {
            if (node != null) {
                stack.push(node);
                node = node.left;
            } else {
                node = stack.pop();
                rt.add(node.val);
                node = node.right;
            }
        }
        return rt;
    }
  • 後序遍歷
    • 申請兩個棧s1,s2,將頭節點壓入s1
    • 從s1中彈出節點cur依次將cur的左孩子右孩子壓入s1,同時將cur壓入棧s2中
    • 最後s2的棧即爲訪問順序,不斷彈出打印即可
public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> rt = new ArrayList<>();
        Stack<TreeNode> stack1 = new Stack<>();
        Stack<TreeNode> stack2 = new Stack<>();
        if (root == null){
            return rt;
        }

        stack1.push(root);

        while (!stack1.empty()){
            TreeNode node = stack1.pop();
            stack2.push(node);
            if (node.left != null){
                stack1.push(node.left);
            }
            if (node.right != null){
                stack1.push(node.right);
            }
        }
        while (!stack2.empty()){
            rt.add(stack2.pop().val);
        }

        return rt;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章