BinaryTree的各種操作,包括求高度、三種深度優先遍歷方式(前序、中序、後續的遞歸和非遞歸)、層次遍歷(寬度優先遍歷)
Leetcode題目:
*1、144 先序遍歷二叉樹
* 2、 94 中序遍歷二叉樹
* 3、145 後序遍歷二叉樹
* 4、102 107 層次遍歷二叉樹
* 5、105 先序序列和中序序列重構二叉樹
* 6、106 後序序列和中序序列重構二叉樹**
import java.util.*;
/**
* BinaryTree的節點定義
*
*/
class TreeNode {
int val;
TreeNode left, right;
public TreeNode(int val) {
this.val = val;
}
}
/**
*
*/
public class BinaryTree {
private TreeNode root;
public BinaryTree(TreeNode root) {
this.root = root;
}
/**
* leetcode NO.144
* 先序遍歷樹,遞歸版本
*
* @param root
*/
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<Integer>();
if (root != null) {
// visit(root);
list.add(root.val);
list.addAll(preorderTraversal(root.left));
list.addAll(preorderTraversal(root.right));
}
return list;
}
/**
* 先序遍歷樹,迭代版本
*
* @param root
* @return
*/
public List<Integer> preorderTraversalIterative(TreeNode root) {
List<Integer> list=new ArrayList<Integer>();
Stack<TreeNode> stack=new Stack<TreeNode>();
TreeNode visit=root;
while(visit!=null || !stack.isEmpty()){
if(visit!=null){ //依次遍歷並訪問所有的左節點,直到左節點爲空,
list.add(visit.val);
stack.push(visit); //將遍歷的每一個節點存儲到棧中
visit=visit.left;
}else{ //遍歷棧訂節點的右節點
visit=stack.pop();
visit=visit.right;
}
}
return list;
}
/**
* leetcode NO.94
* 中序遍歷樹,遞歸版本
* @param root
* @return
*/
public List<Integer> inorderTraversal(TreeNode root){
List<Integer> list=new ArrayList<Integer>();
if(root!=null){
list.addAll(inorderTraversal(root.left));
list.add(root.val);
list.addAll(inorderTraversal(root.right));
}
return list;
}
/**
* 中序遍歷樹,迭代版本;
* @param root
* @return
*/
public List<Integer> inorderTraversalIterative(TreeNode root){
List<Integer> list=new ArrayList<Integer>();
Stack<TreeNode> stack=new Stack<TreeNode>();
TreeNode visit=root;
while(visit!=null || !stack.isEmpty()){
if(visit!=null){ //先遍歷所有左節點,將左節點加入棧中,直到左節點爲空
stack.push(visit);
visit=visit.left;
}else{ //訪問棧頂元素,並遍歷棧頂元素的右節點
visit=stack.pop();
list.add(visit.val); //與前序遍歷的區別是該節點訪問的位置,先入棧再訪問
visit=visit.right;
}
}
return list;
}
/**
* leetcode NO.145
* 後續遍歷樹,遞歸版本
* @param root
* @return
*/
public List<Integer> postorderTraversal(TreeNode root){
List<Integer> list=new ArrayList<Integer>();
if(root!=null){
list.addAll(postorderTraversal(root.left));
list.addAll(postorderTraversal(root.right));
list.add(root.val);
}
return list;
}
/**
*
* 後續遍歷樹,迭代版本
* 後續遍歷的順序是left->right->root,前序遍歷的順序是root->left->right
* 將前序遍歷順序調整成root->right->left,然後倒序輸出,即爲後序遍歷的順序。
* @param root
* @return
*/
public List<Integer> postorderTraversalIterative(TreeNode root){
LinkedList<Integer> list=new LinkedList<Integer>();
Stack<TreeNode> stack=new Stack<TreeNode>();
TreeNode visit=root;
while(visit!=null || !stack.isEmpty()){
if(visit!=null){
list.addFirst(visit.val); //將每一個數據在頭部添加,相當於倒序的效果
stack.push(visit);
visit=visit.right;
}else {
visit=stack.pop();
visit=visit.left;
}
}
return list;
}
/**
* leetcode NO.102
* 層次遍歷,按層次信息添加到二維列表中
* [ [3],[9,20],[15,7]]
* 思路:用兩個隊列存儲當前層的節點和下一層的節點,直到當前層節點個數爲0
* @param root
* @return
*/
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> list=new LinkedList<List<Integer>>();
List<TreeNode> currentQueue=new LinkedList<TreeNode>(); //當前層的節點隊列
if(root==null) return list;
currentQueue.add(root);
while(currentQueue.size()!=0){
List<Integer> currentList=new LinkedList<Integer>(); //當前層節點的值
List<TreeNode> nextQueue=new LinkedList<TreeNode>(); //下一層的節點隊列
for(TreeNode node:currentQueue){
currentList.add(node.val);
if(node.left!=null) nextQueue.add(node.left);
if(node.right!=null) nextQueue.add(node.right);
}
list.add(currentList);
currentQueue=nextQueue;
}
return list;
}
/**
* leetcode NO.107
* For example:
Given binary tree {3,9,20,#,#,15,7},
3
/ \
9 20
/ \
15 7
return its bottom-up level order traversal as:
[
[15,7],
[9,20],
[3]
]
* @param root
* @return
*/
public List<List<Integer>> levelOrderBottom(TreeNode root) {
LinkedList<List<Integer>> list=new LinkedList<List<Integer>>();
List<TreeNode> currentQueue=new LinkedList<TreeNode>(); //當前層的節點隊列
if(root==null) return list;
currentQueue.add(root);
while(currentQueue.size()!=0){
List<Integer> currentList=new LinkedList<Integer>(); //當前層節點的值
List<TreeNode> nextQueue=new LinkedList<TreeNode>(); //下一層的節點隊列
for(TreeNode node:currentQueue){
currentList.add(node.val);
if(node.left!=null) nextQueue.add(node.left);
if(node.right!=null) nextQueue.add(node.right);
}
list.addFirst(currentList); //與levelOrder()的區別僅在於此,每次在鏈表頭部添加,避免了倒序過程
currentQueue=nextQueue;
}
return list;
}
/**
* 5、105 先序序列和中序序列重構二叉樹
* @param preorder
* @param inorder
* @return
*/
public TreeNode buildTreePreIn(int[] preorder, int[] inorder) {
if(preorder.length!=inorder.length || preorder.length==0 || inorder.length==0 )
return null;
return buildTreeProcessor(preorder,0,inorder,0,preorder.length);
}
/**
*
* @param preorder 先序遍歷序列數組
* @param prestart 先序遍歷序列開始下標
* @param inorder 中序遍歷序列數組
* @param instart 中序遍歷序列開始下標
* @param len 序列長度
* @return
*/
public TreeNode buildTreeProcessor
(int[] preorder,int prestart,int[] inorder,int instart,int len){
if(prestart>preorder.length) return null;
TreeNode root=new TreeNode(preorder[prestart]);
int i=0;
while(i<len){ //找到根節點在中序遍歷序列中的位置
if(preorder[prestart]!=inorder[i+instart]){
i++;
}else break;
}
if(i>0){ //如果左子樹存在,遞歸構建左子樹
root.left=buildTreeProcessor(preorder, prestart+1,inorder,instart,i);
}
if(i<len-1){ //如果右子樹存在,遞歸構建右子樹
root.right=buildTreeProcessor(preorder,prestart+1+i,inorder,instart+i+1,len-i-1);
}
return root;
}
/**
* 6、106 後序序列和中序序列重構二叉樹
*/
public static TreeNode buildTreePostIn(int[] inorder, int[] postorder) {
if(inorder.length!=postorder.length || inorder.length==0 || postorder.length==0)
return null;
return buildTreePostInProcessor(inorder,inorder.length-1,postorder,postorder.length-1,inorder.length);
}
/**
*
* @param inorder
* @param instart
* @param postorder 後序遍歷序列
* @param postend 後序遍歷序列尾部下標
* @param len
* @return
*/
public static TreeNode buildTreePostInProcessor
(int[] inorder,int inend,int[] postorder,int postend,int len){
if(postend<0) return null;
TreeNode root=new TreeNode(postorder[postend]);
int i=0;
//找出中序序列中根節點的位置下標,此處從後往前計數(中序和後序都從後往前遍歷)
/*while(i<len ){
if(inorder[i+instart]!=postorder[postend]){
i++;
}else break;
}*/
while(inend-i>=0){
if(inorder[inend-i]!=postorder[postend]){
i++;
}else break;
}
if(i<len-1) root.left=buildTreePostInProcessor(inorder,inend-i-1,postorder,postend-i-1,len-i-1);
if(i>0) root.right=buildTreePostInProcessor(inorder,inend,postorder,postend-1,i);
return root;
}
public static void main(String [] args){
int[] inorder={1,2,3,4};
int[] postorder={1,3,4,2};
buildTreePostIn(inorder,postorder);
}
}