二叉树(一)

求二叉树中的节点个数

求二叉树的深度

前序遍历

中序遍历

后序遍历

分层遍历

二叉树分层左右交替遍历(先从左到右,再从右到左,交替)

求二叉树第K层的节点个数

二叉树中叶子节点的个数

判断两棵二叉树是否相同

判断两个树是否互相镜像

求二叉树的镜像

 

求二叉树中的节点个数

递归

/**
 * 求二叉树中的节点个数递归解法: O(n) 
 * (1)如果二叉树为空,节点个数为0 
 * (2)如果二叉树不为空,二叉树节点个数 = 左子树节点个数 + 右子树节点个数 + 1
 */
public int getNodeNumRec(TreeNode root) {
    if (root == null) {
        return 0;
    } else {
        return getNodeNumRec(root.left) + getNodeNumRec(root.right) + 1;
    }
}

迭代

public int getNodeNum(TreeNode root) {
    if (root == null) {
        return 0;
    }
    int count = 1;
    Queue<TreeNode> queue = new LinkedList<TreeNode>();
    queue.add(root);
    while (!queue.isEmpty()) {
        TreeNode node = queue.remove();
        if (node.left != null) {
            queue.add(node.left);
            count++;
        }
        if (node.right != null) {
            queue.add(node.right);
            count++;
        }
    }
    return count;
}

 求二叉树的深度

递归

/**
 * 求二叉树的深度递归解法: O(n) 
 * (1)如果二叉树为空,二叉树的深度为0 
 * (2)如果二叉树不为空,二叉树的深度 = max(左子树深度, 右子树深度) + 1
 */
public int getDepthRec(TreeNode root) {
    if (root == null) {
        return 0;
    }
    int left = getDepthRec(root.left);
    int right = getDepthRec(root.right);
    return Math.max(left, right) + 1;
}

遍历

public int getDepth(TreeNode root) {
    if (root == null) {
        return 0;
    }
    
    int level = 0;
    int currentLevelNode = 1;
    int nextLevelNode = 0;
    
    Queue<TreeNode> queue = new LinkedList<TreeNode>();
    queue.add(root);
    while (!queue.isEmpty()) {
        TreeNode node = queue.remove();
        currentLevelNode--;
        if (node.left != null) {
            nextLevelNode++;
            queue.add(node.left);
        }
        if (node.right != null) {
            nextLevelNode++;
            queue.add(node.right);
        }

        if (currentLevelNode == 0) {
            level++;
            currentLevelNode = nextLevelNode;
            nextLevelNode = 0;
        }
    }
    return level;
}

 前序遍历

递归

/**
 *  前序遍历递归解法: 
 * (1)如果二叉树为空,空操作 
 * (2)如果二叉树不为空:访问根节点,前序遍历左子树,前序遍历右子树
 */
public void preorderTraversalRec(TreeNode root) {
    if (root == null) {
        return;
    }
    System.out.println(root.val);
    preorderTraversalRec(root.left);
    preorderTraversalRec(root.right);
}

//return list
ArrayList<Integer> list = new ArrayList<>(); 
public ArrayList<Integer> preorderTraversalRec(TreeNode root){
    if(root==null){
        return list;
    }
    list.add(root.val);
    preorderTraversalRec(root.left);
    preorderTraversalRec(root.right);
    return list;
}

 

 非递归

public ArrayList<Integer> preorderTraversal(TreeNode root) {
    ArrayList<Integer> list = new ArrayList<>();  
    if (root == null) {
        return list;
    }
    Stack<TreeNode> stack = new Stack<TreeNode>();
    stack.push(root);
    while (!stack.isEmpty()) {
        TreeNode cur = stack.pop();
        list.add(cur.val);

        if (cur.right != null) {
            stack.push(cur.right);
        }
        if (cur.left != null) {
            stack.push(cur.left);
        }
    }
    return list;
}

 

 中序遍历

 递归

/**
 *  中序遍历递归解法 
 * (1)如果二叉树为空,空操作。 
 * (2)如果二叉树不为空:中序遍历左子树,访问根节点,中序遍历右子树
 */
public void inorderTraversalRec(TreeNode root) {
    if (root == null) {
        return;
    }
    inorderTraversalRec(root.left);
    System.out.println(root.val);
    inorderTraversalRec(root.right);
}

 非递归

public static ArrayList<Integer> inorderTraversal(TreeNode root) {
    ArrayList<Integer> list = new ArrayList<>();
    if (root == null) {
        return list;
    }
    Stack<TreeNode> stack = new Stack<TreeNode>();
    TreeNode cur = root;
    while (true) {
        while (cur != null) {
            stack.push(cur);
            cur = cur.left;
        }
        
        if (stack.isEmpty()) {
            break;
        }

        cur = stack.pop();
        list.add(cur.val);
        cur = cur.right;
    }
    return list;
}

 

 后序遍历

 递归

public void postorderTraversalRec(TreeNode root) {
    if (root == null) {
        return;
    }
    postorderTraversal(root.left);
    postorderTraversal(root.right);
    System.out.println(root.val);
}

 

 非递归

public ArrayList<Integer> postorderTraversal(TreeNode root) {
    ArrayList<Integer> list = new ArrayList<>();
    if (root == null) {
        return list;
    }
    Stack<TreeNode> s = new Stack<TreeNode>(); // 第一个stack用于添加node和它的左右孩子
    Stack<TreeNode> output = new Stack<TreeNode>();// 第二个stack用于翻转第一个stack输出
    s.push(root);
    while (!s.isEmpty()) { // 确保所有元素都被翻转转移到第二个stack
        TreeNode cur = s.pop(); 
        output.push(cur);
        // 把栈顶元素的左孩子和右孩子分别添加入第一个stack
        if (cur.left != null) { 
            s.push(cur.left);
        }
        if (cur.right != null) {
            s.push(cur.right);
        }
    }

    while (!output.isEmpty()) { // 遍历输出第二个stack,即为后序遍历
        list.add(output.pop().val);
    }
    return list;
}

 分层遍历

 递归

public ArrayList<ArrayList<Integer>> levelTraversalRec(TreeNode root) {
    ArrayList<ArrayList<Integer>> ret = new ArrayList<ArrayList<Integer>>();
    dfs(root, 0, ret);
    return ret;
}
private void dfs(TreeNode root, int level, ArrayList<ArrayList<Integer>> ret) {
    if (root == null) {
        return;
    }
    // 添加一个新的ArrayList表示新的一层
    if (level >= ret.size()) {
        ret.add(new ArrayList<Integer>());
    }
    ret.get(level).add(root.val); // 把节点添加到表示那一层的ArrayList里
    dfs(root.left, level + 1, ret); // 递归处理下一层的左子树和右子树
    dfs(root.right, level + 1, ret);
}

 非递归

public ArrayList<Integer> levelTraversal(TreeNode root) {
    ArrayList<Integer> list = new ArrayList<>();
    if (root == null) {
        return list;
    }
    
    Queue<TreeNode> queue = new LinkedList<TreeNode>();
    queue.add(root);
    while (!queue.isEmpty()) {
        TreeNode cur = queue.remove();
        list.add(cur.val);
        if (cur.left != null) {
            queue.add(cur.left);
        }
        if (cur.right != null) {
            queue.add(cur.right);
        }
    }
    return list;
}

 

 二叉树分层左右交替遍历(先从左到右,再从右到左,交替) 

public ArrayList<ArrayList<Integer>> zigzagLevelOrder(TreeNode root) {
    ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
    if(root == null){
        return result;
    }
    
    // 出栈顺序是从左到右
    Stack<TreeNode> leftstack = new Stack<TreeNode>();
    leftstack.push(root);
    
    // 出栈顺序是从右到左
    Stack<TreeNode> rightstack = new Stack<TreeNode>();
    
    boolean left = true;
    
    while(!leftstack.empty() || !rightstack.empty()){
        ArrayList<Integer> list = new ArrayList<Integer>();
        
        if(left){
            int size = leftstack.size();
            for(int i=0; i<size; i++){
                TreeNode node = leftstack.pop();
                list.add(node.val);
                if(node.left!=null){
                    rightstack.push(node.left);
                }
                if(node.right!=null){
                    rightstack.push(node.right);
                }
            }
        }else{
            int size = rightstack.size();
            for(int i=0;i<size;i++){
                TreeNode node = rightstack.pop();
                list.add(node.val);
                if(node.right!=null){
                    leftstack.push(node.right);
                }
                if(node.left!=null){
                    leftstack.push(node.left);
                }
            }
        }
        
        left=!left;
        result.add(list);
    }
    return result;
} 

 

 求二叉树第K层的节点个数

 递归:求以root为根的第k层节点数目 == 求以root.left 为根的k-1层(因为少了root那一层)节点数目 + 以root.right 为根的k-1层节点数目

/**
 *  求二叉树第K层的节点个数 递归解法: 
 * (1)如果二叉树为空或者k<1返回0 
 * (2)如果二叉树不为空并且k==1,返回1 
 * (3)如果二叉树不为空且k>1,返回root左子树中k-1层的节点个数与root右子树k-1层节点个数之和
 */
public int getNodeNumKthLevelRec(TreeNode root, int k) {
    if (root == null || k < 1)
        return 0;
    if (k == 1) 
        return 1;
int numLeft = getNodeNumKthLevelRec(root.left, k - 1); int numRight = getNodeNumKthLevelRec(root.right, k - 1); return numLeft + numRight; }

 

 非递归

// 与求二叉树深度迭代方法一样
public int getNodeNumKthLevel(TreeNode root, int k) {
    if (root == null) {
        return 0;
    }

    Queue<TreeNode> queue = new LinkedList<TreeNode>();
    int i = 0;
    int currentLevelNodes = 1;
    int nextLevelNodes = 0;

    queue.add(root);
    while (!queue.isEmpty() && i < k) {
        TreeNode cur = queue.remove();
        currentLevelNodes--;
        if (cur.left != null) {
            queue.add(cur.left);
            nextLevelNodes++;
        }
        if (cur.right != null) {
            queue.add(cur.right);
            nextLevelNodes++;
        }

        if (currentLevelNodes == 0) { 
            currentLevelNodes = nextLevelNodes;
            nextLevelNodes = 0;
            i++;
        }
    }
    return currentLevelNodes;
}

 

 二叉树中叶子节点的个数

 递归

public int getNodeNumLeafRec(TreeNode root) {
    if (root == null)
        return 0;
    if (root.left == null && root.right == null)
        return 1;
    
    return getNodeNumLeafRec(root.left) + getNodeNumLeafRec(root.right);
}

 

 非递归

// 基于分层遍历方法
public int getNodeNumLeaf(TreeNode root) {
    if (root == null) {
        return 0;
    }

    int leafNodes = 0;
    Queue<TreeNode> queue = new LinkedList<TreeNode>();
    queue.add(root);

    while (!queue.isEmpty()) {
        TreeNode cur = queue.remove();
        if (cur.left != null) {
            queue.add(cur.left);
        }
        if (cur.right != null) {
            queue.add(cur.right);
        }
        if (cur.left == null && cur.right == null) {
            leafNodes++;
        }
    }
    return leafNodes;
}

 

 判断两棵二叉树是否相同

 递归

/**
 *  判断两棵二叉树是否相同的树。 递归解法: 
 * (1)如果两棵二叉树都为空,返回真 
 * (2)如果两棵二叉树一棵为空,另一棵不为空,返回假
 * (3)如果两棵二叉树都不为空,如果对应的左子树和右子树都相同返回真,其他返回假
 */
public boolean isSameRec(TreeNode t1, TreeNode t2){
    if(t1==null && t2==null){
        return true;
    }
    if(t1==null || t2==null){
        return false;
    }
    if(t1.val==t2.val){
        return isSameRec(t1.left, t2.left) && isSameRec(t2.right, t2.right);
    }
    return false;
}

 

 非递归

/**
 *  判断两棵二叉树是否相同的树(迭代) 遍历一遍即可,这里用preorder
 */
public boolean isSame(TreeNode r1, TreeNode r2) {
    if (r1 == null && r2 == null) {
        return true;
    } else if (r1 == null || r2 == null) {
        return false;
    }

    Stack<TreeNode> s1 = new Stack<TreeNode>();
    Stack<TreeNode> s2 = new Stack<TreeNode>();
    s1.push(r1);
    s2.push(r2);

    while (!s1.isEmpty() && !s2.isEmpty()) {
        TreeNode node1 = s1.pop();
        TreeNode node2 = s2.pop();
        if (node2 == null && node1 == null) {
            continue;
        } else if (node1 != null && node2 != null && node1.val == node2.val) {
            s1.push(node1.right);
            s1.push(node1.left);
            s2.push(node2.right);
            s2.push(node2.left);
        } else {
            return false;
        }
    }
    return true;
}

 

 判断两个树是否互相镜像

public boolean isMirrorRec(TreeNode r1, TreeNode r2) {
    if (r1 == null && r2 == null) {
        return true;
    }
    if (r1 == null || r2 == null) {
        return false;
    }

    if (r1.val != r2.val) {
        return false;
    }

    return isMirrorRec(r1.left, r2.right) && isMirrorRec(r1.right, r2.left);
}

 

 求二叉树的镜像

 递归

public TreeNode mirrorCopyRec(TreeNode root) {
    if (root == null) {
        return null;
    }

    TreeNode newNode = new TreeNode(root.val);
    newNode.left = mirrorCopyRec(root.right);
    newNode.right = mirrorCopyRec(root.left);
    return newNode;
}

 非递归

// 1. 破坏原来的树,把原来的树改成其镜像
public void mirror(TreeNode root) {
    if (root == null) {
        return;
    }

    Stack<TreeNode> stack = new Stack<TreeNode>();
    stack.push(root);
    while (!stack.isEmpty()) {
        TreeNode cur = stack.pop();

        TreeNode temp = cur.left;
        cur.right = cur.left;
        cur.left = temp;

        if (cur.right != null) {
            stack.push(cur.right);
        }
        if (cur.left != null) {
            stack.push(cur.left);
        }
    }
}

// 2. 不破坏原来的树,返回一个新的镜像树
public static TreeNode mirrorCopy(TreeNode root) {
    if (root == null) {
        return root;
    }

    Stack<TreeNode> stack = new Stack<TreeNode>();
    Stack<TreeNode> newStack = new Stack<TreeNode>();
    stack.push(root);
    TreeNode newRoot = new TreeNode(root.val);
    newStack.push(newRoot);

    while (!stack.isEmpty()) {
        TreeNode cur = stack.pop();
        TreeNode newCur = newStack.pop();

        if (cur.right != null) {
            stack.push(cur.right);
            newCur.left = new TreeNode(cur.right.val);
            newStack.push(newCur.left);
        }
        if (cur.left != null) {
            stack.push(cur.left);
            newCur.right = new TreeNode(cur.left.val);
            newStack.push(newCur.right);
        }
    }
    return newRoot;
}

 

posted @ 2016-06-09 22:24  Hesier  阅读(181)  评论(0编辑  收藏  举报