package com.niukeprocess.practiceofbtree;
import java.lang.reflect.Array;
import java.util.*;
public class DepthOfBTree {
public static void main(String[] args) {
}
//1.遞歸求二叉樹的深度
public static int maxTreeDepth(TreeNode root){
if(root == null) return 0;
int left=maxTreeDepth(root.left);
int right=maxTreeDepth(root.right);
return (left>right)?(left+1):(right+1);
}
//2.非遞歸求二叉樹的深度,藉助輔助數據結構隊列,廣度優先遍歷二叉樹
public static int heigthOfTree(TreeNode root){
if(root==null){
return 0;
}
ArrayDeque<TreeNode> queue= new ArrayDeque<TreeNode>();
int height =0;
queue.add(root);
while(!queue.isEmpty()){
int size=queue.size();
for(int i=0;i<size;i++){
TreeNode node=queue.removeFirst();
if(node.left!=null){
queue.add(node.left);
}
if(node.right!=null){
queue.add(node.right);
}
}
height++;
}
return height;
}
//3.求二叉樹的最小深度
public static int minDepthOfTree(TreeNode root){
if(root == null) return 0;
int left = minDepthOfTree(root.left);
int right =minDepthOfTree(root.right);
if(left ==0&& right>0) return right+1;
else if(right==0 && left>0) return left+1;
else return (left<right)?(left+1):(right+1);
}
//4.求二叉樹中結點的個數
public static int sumOfTree(TreeNode root){
if(root ==null) return 0;
int left=sumOfTree(root.left);
int right=sumOfTree(root.right);
return 1+left+right;
}
//5.求二叉樹中葉子節點的個數
public static int numOfLeaf(TreeNode root ){
if(root == null) return 0;
int count=0;
if(root.left==null && root.right==null) count++;
numOfLeaf(root.right);
numOfLeaf(root.left);
return count;
}
//6.求二叉樹中第k層節點的個數
public static int KLevelLeafNode(TreeNode root,int kLevel){
if(root ==null || kLevel <=0) return 0;
if(root != null && kLevel==1) return 1;
return (KLevelLeafNode(root.left,kLevel-1)+KLevelLeafNode(root.right,kLevel-1));
}
//7.判斷二叉樹是否爲平衡二叉樹
//平衡二叉樹就是左子樹和右子樹的高度差不能超過1,且左右子樹必須是平衡二叉樹,且左右子樹必須是平衡二叉樹
public static boolean IsBalanced(TreeNode root){
if(root == null) return true;
if(Math.abs(maxTreeDepth(root.left)-maxTreeDepth(root.right))<=1){
return (IsBalanced(root.left) && IsBalanced(root.right));
}else{
return false;
}
}
//8.判斷二叉樹是否是完全二叉樹
/**
* 判斷一個樹是否屬於完全二叉樹可以從以下2個條件來判斷:
* 層次遍歷二叉樹
* 1.任何一個結點如果右孩子不爲空,左孩子卻是空,則一定不是完全二叉樹;
* 2.當一個節點出現右孩子爲空時候,判斷該節點的層次遍歷後繼結點是否爲葉子
* 節點,如果全部都是葉子節點,則是完全二叉樹,如果存在任何一個結點不是葉
* 子結點,則一定不是完全二叉樹
*
*
*/
public static boolean isCBT(TreeNode node){
if(node ==null) return false;
TreeNode leftChild=null;
TreeNode rightChild=null;
boolean left=false;//葉節點判斷標誌
Queue<TreeNode> queue=new LinkedList<TreeNode>();
queue.offer(node);
while(!queue.isEmpty()){
TreeNode head=queue.poll();
leftChild=head.left;
rightChild=head.right;
//右孩子不等於空,左孩子等於空-->false
if((rightChild!=null && leftChild==null) ||
//開啓葉節點判斷標誌位時,如果層次遍歷中的後繼結點不是葉節點-->false
(left && (rightChild!=null || leftChild!=null))){
return false;
}
if(leftChild != null){
queue.offer(leftChild);
}
if(rightChild != null){
queue.offer(rightChild);
}else {
left = true;
}
}
return true;
}
/**
* 9.兩個二叉樹是否完全相同
* 基本思想:如果兩棵樹都爲空則相同
* 如果其中一顆數爲空,則不同
* 如果兩棵誰都不爲空,則判斷左右子樹是否相同
*
*/
public static boolean IsSame(TreeNode first,TreeNode second){
if(first == null && second == null) return true;
else if(first ==null || second == null) return false;
if(first != null && second !=null){
if(first.data != second.data) return false;
else return IsSame(first.left,second.left) && IsSame(first.right,second.right);
}
return false;
}
/**
* 10.兩個二叉樹是否互爲鏡像(對稱)
* 基本思想:
* 首先判斷這棵樹是否爲空樹,如果空樹則直接返回true
* 如果不爲空,則進行分類:
* case1:節點左右子樹爲空,則直接返回true
* case2;節點的左右子樹有一個爲空,則直接返回false
* case3:節點的左右子樹均不爲空,則判斷節點的左右子節點的值是否相等
* 並且判斷左節點的子左節點和右節點的右子節點是否對稱
* 還有左節點的右子節點和右節點的左子節點是否對稱
*/
public static boolean IsSymmetry(TreeNode root){
if(root == null) return true;
return IsSymmetry(root.left, root.right);
}
private static boolean IsSymmetry(TreeNode left, TreeNode right) {
if(left == null && right == null ) return true;
if(left == null || right == null) return false;
return left.data == right.data && IsSymmetry(left.left,right.right) && IsSymmetry(left.right,right.left);
}
/**
*
* 11.翻轉二叉樹或鏡像二叉樹
*
*/
public static TreeNode invertTree(TreeNode root){
if(root == null) return null;
TreeNode left = invertTree(root.left);
TreeNode right = invertTree(root.right);
root.left=right;
root.right=left;
return root;
}
/**
* 12.求兩個二叉樹的最低公共祖先節點
*
*/
public static TreeNode findParent(TreeNode root,TreeNode node1,TreeNode node2) {
if(findNode(root.left,node1)){
if(findNode(root.right,node2)) return root;
else return findParent(root.left,node1,node2);
}else{
if(findNode(root.left,node2)) return root;
else return findParent(root.right,node1,node2);
}
}
public static boolean findNode(TreeNode root,TreeNode node){
if(root == null || node == null) return false;
if(root == node) return true;
boolean found = findNode(root.left,node);
if(!found) found=findNode(root.right,node);
return found;
}
/**
* 二叉樹的前序遍歷
*/
//遞歸解法
public static ArrayList<Integer> preOrderReverse(TreeNode root){
ArrayList<Integer> result = new ArrayList<Integer>();
preOrder2(root ,result);
return result;
}
private static void preOrder2(TreeNode root, ArrayList<Integer> result) {
if(root == null ) return;
result.add((Integer) root.data);
preOrder2(root.left,result);
preOrder2(root.right,result);
}
//迭代解法
public static ArrayList<Integer> preOrder(TreeNode root){
Stack<TreeNode> stack =new Stack<TreeNode>();
ArrayList<Integer> list=new ArrayList<Integer>();
if(root == null) return list;
stack.push(root);
while(!stack.isEmpty()){
TreeNode node=stack.pop();
list.add((Integer) node.data);
if(node.right!=null) stack.push(node.right);
if(node.left !=null) stack.push(node.left);
}
return list;
}
//二叉樹的中序遍歷
public static ArrayList<Integer> inOrder(TreeNode root){
ArrayList<Integer> list= new ArrayList<Integer>();
Stack<TreeNode> stack =new Stack<TreeNode>();
TreeNode cur=root;
while(cur!=null || !stack.isEmpty()){
while(cur!=null){
stack.add(cur);
cur=cur.left;
}
cur=stack.peek();
stack.pop();
list.add((Integer) cur.data);
cur=cur.right;
}
return list;
}
//二叉樹的後序遍歷
public static ArrayList<Integer> postOrder(TreeNode root){
ArrayList<Integer> list =new ArrayList<Integer>();
if(root == null) return list;
list.addAll(postOrder(root.left));
list.addAll(postOrder(root.right));
list.add((Integer) root.data);
return list;
}
/**
* 前序遍歷和後序遍歷構造二叉樹
*/
/**
* 輸入一個二叉樹和一個整數,打印出二叉樹中結點值的和等於輸入整數
* 所有的路徑
*/
public static void findPath(TreeNode root,int i){
if(root == null) return;
Stack<Integer> stack =new Stack<Integer>();
int currentSum=0;
findPath(root,i,stack,currentSum);
}
private static void findPath(TreeNode root, int i, Stack<Integer> stack, int currentSum) {
currentSum+=(Integer) root.data;
stack.push((Integer)root.data);
if(root.left == null && root.right==null){
if(currentSum== i){
for(int path:stack){
System.out.println(path);
}
}
}
if(root.left != null) findPath(root.left,i,stack,currentSum);
if(root.right !=null) findPath(root.right,i,stack,currentSum);
stack.pop();
}
/**
* 二叉樹的層次遍歷
*/
public static ArrayList<ArrayList<Integer>> levelOrder(TreeNode root){
ArrayList<ArrayList<Integer>> result=new ArrayList<ArrayList<Integer>>();
if(root == null) return result;
Queue<TreeNode> queue=new LinkedList<TreeNode>();
queue.offer(root);
while(!queue.isEmpty()){
int size=queue.size();
ArrayList<Integer> level=new ArrayList<Integer>();
for(int i=0;i<size;i++){
TreeNode node=queue.poll();
level.add((Integer) node.data);
if(node.left !=null) queue.offer(node.left);
if(node.right !=null) queue.offer(node.right);
}
result.add(level);
}
return result;
}
}