資料結構之你真的瞭解二叉樹嗎
簡述
你真的瞭解二叉樹嗎?
一棵二叉樹是結點的一個有限集合,該集合或者為空,或者是由一個根節點加上兩棵別稱為左子樹和右子樹的二叉樹組成。
這是表面上的二叉樹,本文將基於二叉樹的前中後序遍歷解決一些求解二叉樹的相關問題,感興趣的就繼續往下看吧。
定義二叉樹的結點
二叉樹是結點的有限集合,那麼結點就必不可少啦:
public class TreeNode {
public TreeNode left;
public TreeNode right;
public int value;
public TreeNode(int value) {
this.value = value;
}
}
二叉樹的前中後序遍歷
二叉樹的前中後序遍歷運用了遞迴的方法,根結點單獨考慮,然後對左右子樹採用相同的方法:
public class TreeTraversal {
//前序遍歷
public static void preTraversal(Node root){
if(root!=null) {
System.out.printf("%c",root.val);
preTraversal(root.left);
preTraversal(root.right);
}else{
//不處理
}
}
//中序遍歷
public static void inTraversal(Node root){
if(root!=null){
inTraversal(root.left);
System.out.printf("%c",root.val);
inTraversal(root.right);
}else{}
}
//後序遍歷
public static void postTraversal(Node root){
if(root!=null){
postTraversal(root.left);
postTraversal(root.right);
System.out.printf("%c",root.val);
}else{}
}
}
你品,你細品,這方法是不是很巧妙,那麼接下來,別眨眼,套路他這就來了…
計算結點個數
計算二叉樹結點的個數
public static int sumNodeSize(Node root){
if(root==null){
return 0;
}else {
int rootNodeSize = 1;//根結點單獨考慮
//對左右子樹採用相同的方法
int leftNodeSize = sumNodeSize(root.left);
int rightNOdeSize = sumNodeSize(root.right);
return rootNodeSize + leftNodeSize + rightNOdeSize;
}
}
第k層結點個數
求二叉樹第k層結點個數
public static int sumKlevelNodeSize(TreeNode root,int k){
//根結點單獨考慮
if(root==null){
return 0;
}else if(k==1){
return 1;
}else{
//對左右子樹採用相同的方法
int leftsumk_1=sumKlevelNodeSize(root.left,k-1);
int rightsumk_1=sumKlevelNodeSize(root.right,k-1);
return leftsumk_1+rightsumk_1;
}
}
二叉樹的高度
給定一棵二叉樹,求它的高度:
public static int getHeight(TreeNode root){
//根結點單獨考慮
if(root==null){
return 0;
}else if(root.left==null&&root.right==null){
return 1;
}else{
//對左右子樹採用相同的方法
int leftheight=getHeight(root.left);
int rightheight=getHeight(root.right);
return Math.max(leftheight,rightheight)+1;
}
}
是否有結點值為v
給定一棵二叉樹,給定一個值,判斷二叉樹中是否包含值為指定值的結點:
public static boolean contains(TreeNode root,int v){
//根結點單獨考慮
if(root==null){
return false;
}else if(root.value==v){
return true;
}else{
//對左右子樹採用相同的方法
boolean leftCon=contains(root.left,v);
if(leftCon){
return true;
}else {
boolean rightCon=contains(root.right,v);
if(rightCon){
return true;
}else{
return false;
}
}
}
}
怎麼樣是不是很驚喜,我連註釋的文案都沒改呢。
下面再奉上一些相關面試題,裡面也有相關應用,入股不虧!
平衡二叉樹
輸入一棵二叉樹的根節點,判斷該樹是不是平衡二叉樹。如果某二叉樹中任意節點的左右子樹的深度相差不超過1,那麼它就是一棵平衡二叉樹。
此處提供一種思路:求結點左右子樹高度再通過高度差判斷是否為平衡二叉樹。
public class balanceTreeJZ55 {
public boolean isBalanced(TreeNode root) {
//單獨考慮根結點
if(root==null){
return true;
}
//用到剛才求高度的方法
int lefth=getHeight(root.left);
int righth=getHeight(root.right);
int dif=lefth-righth;
//判斷高度差是否<=1
if(!(dif==-1||dif==0||dif==1)){
return false;
}
//對左右子樹採用相同的方法 得到的結果結合得出最終結果
return isBalanced(root.left)&&isBalanced(root.right);
}
private int getHeight(TreeNode root) {
if(root==null){
return 0;
}
return Math.max(getHeight(root.right),getHeight(root.left))+1;
}
}
另一個樹的子樹
給定兩個非空二叉樹 s 和 t,檢驗 s 中是否包含和 t 具有相同結構和節點值的子樹。s 的一個子樹包括 s 的一個節點和這個節點的所有子孫。s 也可以看做它自身的一棵子樹。
來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/subtree-of-another-tree
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。
此處提供一種思路:如果s為空樹,那麼一定返回false,如果s跟q的值相等,那麼需要單獨判斷他們兩是否為相同的樹,相同的話,就返回true,不相同繼續判斷,最後,繼續判斷左子樹右子樹是否包含就可以了。
public class isSonTree572 {
//判斷是否為相同樹
public boolean isSameTree(TreeNode p, TreeNode q) {
//兩者皆為空樹
if(p==null&&q==null){
return true;
}
//有一個是空樹
if(p==null||q==null){
return false;
}
//根結點相等並且左右子樹也互為相同樹
return p.value==q.value&&isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);
}
public boolean isSubtree(TreeNode s, TreeNode t) {
//s為空時
if(s==null){
return false;
}
//根結點就相等時
if(s.value==t.value){
if(isSameTree(s,t)){
return true;
}
}
//通過對左右子樹採用相同的方法 判斷左右子樹是否有該子樹
if(isSubtree(s.left,t)){
return true;
}
return isSubtree(s.right,t);
}
}
二叉樹的最近公共祖先
給定一個二叉樹, 找到該樹中兩個指定節點的最近公共祖先。
百度百科中最近公共祖先的定義為:“對於有根樹 T 的兩個結點 p、q,最近公共祖先表示為一個結點 x,滿足 x 是 p、q 的祖先且 x 的深度儘可能大(一個節點也可以是它自己的祖先)。”
來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。
此處提供一種方法,當兩個結點都在左子樹中那麼最近公共祖先也在裡面(右同),如果一個在左子樹,一個在右子樹那麼最近公共祖先就是根結點。需要單獨寫一個方法判斷結點是在左子樹還是右子樹,詳見程式碼:
public class nearestAncestor236 {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
//根結點單獨考慮
if(p==root||q==root){
return root;
}
//對左右子樹採用相同的方法
boolean pInleft=search(root.left,p);
boolean qInleft=search(root.left,q);
//兩個結點都在左子樹
if(pInleft&&qInleft){
return lowestCommonAncestor(root.left,p,q);
}
//兩個結點都在右子樹
else if(!pInleft&&!qInleft){
return lowestCommonAncestor(root.right,p,q);
}
//一個在左 一個在右 最近祖先為根結點
else{
return root;
}
}
//單獨寫一個方法判斷結點在左子樹還是右子樹 即判斷以root為跟的子樹裡是否有t結點
private boolean search(TreeNode root, TreeNode t) {
//根為空
if(root==null){
return false;
}
//跟結點就是
if(root==t){
return true;
}
//對左右子樹採用相同的方法
return search(root.left,t)||search(root.right,t);
}
}
好啦,看了這麼多題目是不是有暈,反正小編是有點腦殼疼了,慢慢消化吧,我們下期再見,如有誤之處還請批評指正。
相關文章
- 注意!JS的結構你真的瞭解嗎?JS
- 資料結構之「二叉樹」資料結構二叉樹
- 重學資料結構之樹和二叉樹資料結構二叉樹
- 你真的瞭解RPC嗎?RPC
- 你真的瞭解@Async嗎?
- ViewStub你真的瞭解嗎View
- 你真的瞭解 Array 嗎?
- 你真的瞭解mongoose嗎?Go
- 你真的瞭解HTAP嗎
- 你真的瞭解URLEncode嗎?
- 資料結構(樹):二叉樹資料結構二叉樹
- 資料結構之「二叉搜尋樹」資料結構
- 資料結構 - 二叉樹資料結構二叉樹
- 資料結構-二叉樹資料結構二叉樹
- 常用資料結構之線索二叉樹資料結構二叉樹
- 你真的瞭解前端路由嗎?前端路由
- JavaScript 你真的瞭解this指向嗎JavaScript
- 你真的瞭解過 ConcurrentHashMap 嗎?HashMap
- 資料結構-平衡二叉樹資料結構二叉樹
- 你真的瞭解js運算子嗎JS
- 你真的瞭解npm-scripts嗎?NPM
- 你真的瞭解 Cookie 和 Session 嗎CookieSession
- 高併發,你真的瞭解嗎?
- 你真的瞭解 sync.Once 嗎
- 你真的瞭解深度學習嗎?深度學習
- 你真的瞭解 Cookie 和 Session 嗎?CookieSession
- 你真的瞭解 Session 和 Cookie 嗎?SessionCookie
- 你真的懂Redis的5種基本資料結構嗎?Redis資料結構
- 資料結構之樹結構概述(含滿二叉樹、完全二叉樹、平衡二叉樹、二叉搜尋樹、紅黑樹、B-樹、B+樹、B*樹)資料結構二叉樹
- 你真的瞭解python嗎?這篇文章帶你快速瞭解!Python
- 資料結構之「樹」資料結構
- 你真的瞭解資料在堆疊中的儲存方式嗎?
- 資料結構 二叉樹遍歷資料結構二叉樹
- 【資料結構】二叉搜尋樹!!!資料結構
- 資料結構二叉樹學習資料結構二叉樹
- 資料結構-二叉樹、堆、圖資料結構二叉樹
- 資料結構-二叉搜尋樹資料結構
- 資料結構——二叉樹進階資料結構二叉樹