劍指offer上一道比較基礎的題目,但這個解法不僅可以求二叉樹的深度同時可以求二叉樹的最大層數,某一層的某一個節點 是一種比較通用的方法!
先建立數據模型
package Binary_tree;
public class Node {//二叉樹節點
private int data;
private Node leftNode;
private Node rightNode;
public Node(int data, Node leftNode, Node rightNode){
this.data = data;
this.leftNode = leftNode;
this.rightNode = rightNode;
}
public int getData(){
return data;
}
public void setData(int data){
this.data = data;
}
public Node getLeftNode(){
return leftNode;
}
public void setLeftNode(Node leftNode){
this.leftNode = leftNode;
}
public Node getRightNode(){
return rightNode;
}
public void setRightNode(Node rightNode){
this.rightNode = rightNode;
}
}
遞歸解法比較簡單:
private int getDeep(Node node){
if(node==null) return 0; //遞歸出口
int left = getDeep(node.getLeftNode()); //遞歸求左樹深度
int right = getDeep(node.getRightNode()); //遞歸求右樹深度
return Math.max(left, right)+1; //算上根節點返回左右樹深度大值+1
}
非遞歸解法:
以該樹爲例:
A
/ \
B C
/ \ /
D E F
\ / \
G H J
-
經典的非遞歸層次遍歷:利用輔助隊列,先將頭節點入隊列,當隊列不空時出隊列的節點記爲current,
當current左節點不空時入隊列,其右節點不空時入隊列,如此循環即可。
求深度:構造變量cur記錄當前層訪問到的節點數,width記錄當前層的總個數,每當訪問過一層層數deep++;
此種方法同時可以求最大寬度,訪問第幾層的第幾個節點,是一種通用方法
package Binary_tree;
import java.util.LinkedList;
import static net.mindview.util.Print.*;
public class Deep {
public static Node init(){
Node J = new Node(8, null, null);
Node H = new Node(4, null, null);
Node G = new Node(2, null, null);
Node F = new Node(7, null, J);
Node E = new Node(5, H, null);
Node D = new Node(1, null, G);
Node C = new Node(9, F, null);
Node B = new Node(3, D, E);
Node A = new Node(6, B, C);
return A; //返回根節點
}
private void getDeep1(Node root,int d,int n){
Node result=null;
Node current; //記錄當前節點
LinkedList<Node> queue = new LinkedList<Node>(); //聲明輔助隊列
int cur, width , deep=0 , maxwidth=0; //cur記錄當前層所訪問的個數,width爲當前層的個數,deep記錄層數
queue.offer(root);
while(!queue.isEmpty()){
cur=0;
width=queue.size(); //當前隊列中所含元素的個數便是該層樹的寬度
if(width>maxwidth) maxwidth=width; //若當前寬度大於最大寬度,則將當前寬度設爲最大寬度
while(cur<width){
current=queue.poll();
if(deep+1==d&&cur+1==n) //找到符合條件的節點
result=current;
if(current.getLeftNode()!=null) //左節點存在則入隊列
queue.offer(current.getLeftNode());
if(current.getRightNode()!=null) //右節點存在則入隊列
queue.offer(current.getRightNode());
cur++;
}
deep++;
}
System.out.println("當前二叉樹的深度爲:"+deep+ " 其最大層數爲:"+maxwidth);
System.out.println("該二叉樹中第"+d+"層的第"+n+"個節點值爲:"+result.getData());
}
private int getDeep(Node node){
if(node==null) return 0; //遞歸出口
int left = getDeep(node.getLeftNode()); //遞歸求左樹深度
int right = getDeep(node.getRightNode()); //遞歸求右樹深度
return Math.max(left, right)+1; //算上根節點返回左右樹深度大值+1
}
public static void main(String[] args){
Deep obj = new Deep();
Node root = Deep.init();
obj.getDeep1(root, 3, 2); //尋找第三層的第二個節點,默認輸入是有效的,本應該要做輸入判斷該點是否存在的
//在這裏主要是介紹該算法的思想就沒有去判斷。
}
}
輸出爲:
當前二叉樹的深度爲:4 其最大層數爲:3
該二叉樹中第3層的第2個節點值爲:5