區別:
1) 二叉樹的深度優先遍歷的非遞歸的通用做法是采用棧,廣度優先遍歷的非遞歸的通用做法是采用隊列。
2) 深度優先遍歷:對每一個可能的分支路徑深入到不能再深入為止,而且每個結點只能訪問一次。要特別注意的是,二叉樹的深度優先遍歷比較特殊,可以細分為先序遍歷、中序遍歷、后序遍歷。具體說明如下:
- 先序遍歷:對任一子樹,先訪問根,然后遍歷其左子樹,最后遍歷其右子樹。
- 中序遍歷:對任一子樹,先遍歷其左子樹,然后訪問根,最后遍歷其右子樹。
- 后序遍歷:對任一子樹,先遍歷其左子樹,然后遍歷其右子樹,最后訪問根。
廣度優先遍歷:又叫層次遍歷,從上往下對每一層依次訪問,在每一層中,從左往右(也可以從右往左)訪問結點,訪問完一層就進入下一層,直到沒有結點可以訪問為止。
3)深度優先搜素算法:不全部保留結點,占用空間少;有回溯操作(即有入棧、出棧操作),運行速度慢。
廣度優先搜索算法:保留全部結點,占用空間大; 無回溯操作(即無入棧、出棧操作),運行速度快。
通常 深度優先搜索法不全部保留結點,擴展完的結點從數據庫中彈出刪去,這樣,一般在數據庫中存儲的結點數就是深度值,因此它占用空間較少。
所以,當搜索樹的結點較多,用其它方法易產生內存溢出時,深度優先搜索不失為一種有效的求解方法。
廣度優先搜索算法,一般需存儲產生的所有結點,占用的存儲空間要比深度優先搜索大得多,因此,程序設計中,必須考慮溢出和節省內存空間的問題。
但廣度優先搜索法一般無回溯操作,即入棧和出棧的操作,所以運行速度比深度優先搜索要快些
深度優先:
前序遍歷:35,20,15,16,29,28,30,40,50,45,55
中序遍歷:15,16,20,28,29,30,35,40,45,50,55
后序遍歷:16,15,28,30,29,20,45,55,50,40,35
廣度優先遍歷:35 20 40 15 29 50 16 28 30 45 55
代碼:
package www.hhy; import java.beans.beancontext.BeanContextChild; import java.util.*; class Binarytree { class TreeNode{ int value; TreeNode left; TreeNode right; public TreeNode(int value) { this.value = value; } } //用遞歸創建二叉樹 public int i = 0; TreeNode creatTesttree(String s){ TreeNode root = null; if (s.charAt(i)!='#') { root = new TreeNode(s.charAt(i)); i++; root.left = creatTesttree(s); root.right = creatTesttree(s); } else{ i++; } return root; } //二叉樹的前序遍歷遞歸 void binaryTreePrevOrder(TreeNode root){ if(root==null){ return; } System.out.println(root.value+" "); binaryTreePrevOrder(root.left); binaryTreePrevOrder(root.right); } //二叉樹的中序遍歷遞歸 void binaryTreeInOrder(TreeNode root){ if(root==null){ return; } binaryTreeInOrder(root.left); System.out.println(root.value+" "); binaryTreeInOrder(root.right); } //二叉樹的后續遍歷遞歸 void binaryTreePostOrder(TreeNode root){ if(root==null){ return; } binaryTreePostOrder(root.left); binaryTreePostOrder(root.right); System.out.println(root.value+" "); } //層序遍歷 void binaryTreeLevelOrder(TreeNode root,int level){ if(root ==null||level<1){ return; } if(level==1){ System.out.print(root.value+" "); } binaryTreeLevelOrder(root.left,level-1); binaryTreeLevelOrder(root.right,level-1); } void BTreeLevelOrder(TreeNode root) { if (root == null) return; int dep = getHeight(root); for (int i = 1; i <= dep; i++) { binaryTreeLevelOrder(root,i); } } //二叉樹的層序遍歷 非遞歸 void binaryTreeLevelOrder(TreeNode root) { Queue<TreeNode> queue = new LinkedList<>(); if(root != null) { queue.offer(root); //LinkedList offer add } while (!queue.isEmpty()) { //1、拿到隊頭的元素 把隊頭元素的左右子樹入隊 TreeNode cur = queue.poll(); System.out.print(cur.value+" "); //2、不為空的時候才能入隊 if(cur.left != null) { queue.offer(cur.left); } if(cur.right != null) { queue.offer(cur.right); } } } //二叉樹的前序遍歷非遞歸 void binaryTreePrevOrderNonR(TreeNode root){ Stack<TreeNode> stack = new Stack<>(); TreeNode cur = root; TreeNode top = null; while (cur != null || !stack.empty()) { while (cur != null) { stack.push(cur); System.out.print(cur.value + " "); cur = cur.left; } top = stack.pop(); cur = top.right; } System.out.println(); } //二叉樹的中序遍歷非遞歸 void binaryTreeInOrderNonR(TreeNode root){ Stack<TreeNode> stack = new Stack<>(); TreeNode cur = root; TreeNode top = null; while (cur != null || !stack.empty()) { while (cur != null) { stack.push(cur); cur = cur.left; } top = stack.pop(); System.out.print(top.value+" "); cur = top.right; } System.out.println(); } //二叉樹的后序遍歷非遞歸 void binaryTreePostOrderNonR(TreeNode root) { Stack<TreeNode> stack = new Stack<>(); TreeNode cur = root; TreeNode prev = null; while (cur != null || !stack.empty()) { while (cur != null) { stack.push(cur); cur = cur.left; } cur = stack.peek();//L D //cur.right == prev 代表的是 cur的右邊已經打印過了 if(cur.right == null || cur.right == prev) { stack.pop(); System.out.println(cur.value); prev = cur; cur = null; }else { cur = cur.right; } } } //二叉樹的節點個數遞歸 int getSize(TreeNode root){ if(root==null){ return 0; } return getSize(root.left)+getSize(root.right)+1; } //二叉樹的葉子節點的個數遞歸 int getLeafSize(TreeNode root){ if(root==null){ return 0; } if(root.left==null && root.right==null){ return 1; } return getLeafSize(root.left)+getLeafSize(root.right); } //二叉樹得到第K層結點的個數 int getKlevelSize(TreeNode root ,int k){ if(root==null){ return 0; } if(k == 1){ return 1; } return getKlevelSize(root.left,k-1)+getKlevelSize(root.right,k-1); } //二叉樹查找並返回該結點遞歸 // 查找,依次在二叉樹的 根、左子樹、 // 右子樹 中查找 value,如果找到,返回結點,否則返回 null TreeNode find(TreeNode root, int value){ if(root == null) { return null; } if(root.value == value){ return root; } TreeNode ret = find(root.left,value); if(ret != null) { return ret; } ret = find(root.right,value); if(ret != null) { return ret; } return null; } //二叉樹的高度 int getHeight(TreeNode root){ if(root==null){ return 0; } int leftHeight = getHeight(root.left); int rightHeight = getHeight(root.right); return leftHeight>rightHeight ? leftHeight+1:rightHeight+1; } //判斷一個樹是不是完全二叉樹 public int binaryTreeComplete(TreeNode root) { Queue<TreeNode> queue = new LinkedList<TreeNode>(); if(root != null) { queue.add(root);//offer } while(!queue.isEmpty()) { TreeNode cur = queue.peek(); queue.poll(); if(cur != null) { queue.add(cur.left); queue.add(cur.right); }else { break; } } while(!queue.isEmpty()) { TreeNode cur = queue.peek(); if (cur != null){ //說明不是滿二叉樹 return -1; }else{ queue.poll(); } } return 0;//代表是完全二叉樹 } //檢查兩棵樹是否是相同的,如果兩棵樹結構相同,並且在結點上的值相同,那么這兩棵樹是相同返回true public boolean isSameTree(TreeNode p,TreeNode q){ if((p==null&&q!=null)||(p!=null&&q==null)){ return false; } if(p==null && q==null){ return true; } if(p.value!=q.value){ return false; } return isSameTree(p.left,q.left)&&isSameTree(p.right,q.left); } //檢查是否為子樹 public boolean isSubTree(TreeNode s,TreeNode t){ if(s==null||t==null){ return false; } if(isSameTree(s,t)){ return true; } else if (isSubTree(s.left,t)){ return true; } else if(isSubTree(s.right,t)){ return true; } else{ return false; } } //1.判斷是否為平衡二叉樹,左右子樹的高度之差不超過 "1"(大根本身是平衡二叉樹,左右子樹也必須是平衡二叉樹) // 時間復雜度為n^2 //2.求復雜度為O(n)的解法 public boolean isBanlanced(TreeNode root){ if(root==null){ return true; } else{ int leftHeight = getHeight(root.left); int rightHeight = getHeight(root.right); return Math.abs(leftHeight-rightHeight)<2 &&isBanlanced(root.left) &&isBanlanced(root.right); } } //判斷是否為對稱二叉樹 public boolean isSymmetric(TreeNode root){ if(root==null){ return true; } return isSymmetric(root.left,root.right); } public boolean isSymmetric(TreeNode lefttree,TreeNode righttree){ if((lefttree==null && righttree!=null)||(lefttree!=null && righttree ==null)){ return false; } if(lefttree == null && righttree == null){ return true; } return lefttree.value == righttree.value && isSymmetric(lefttree.left,righttree.right) && isSymmetric(lefttree.right,righttree.left); } //二叉樹創建字符串 非遞歸寫法 public String tree2str(TreeNode t){ StringBuilder sb = new StringBuilder(); tree2strchild(t,sb); return sb.toString(); } public void tree2strchild(TreeNode t ,StringBuilder sb){ if (t==null){ return; } sb.append(t.value); if (t.left!=null){ sb.append("("); tree2strchild(t.left,sb); sb.append(")"); } else { if (t.right==null){ } } } //二叉樹字符串 遞歸寫法 public String CreateStr(TreeNode t){ if(t==null){ return ""; } if(t.left==null&&t.right==null){ return t.value+""; } if(t.left==null){ return t.value+"()"+"("+CreateStr(t.right)+")"; } if(t.right==null){ return t.value+"("+CreateStr(t.left)+")"; } return t.value+"("+CreateStr(t.left)+")"+"("+CreateStr(t.right)+")"; } public int rob(TreeNode root) { if (root == null) return 0; return Math.max(robOK(root), robNG(root)); } private int robOK(TreeNode root) { if (root == null) return 0; return root.value + robNG(root.left) + robNG(root.right); } private int robNG(TreeNode root) { if (root == null) return 0; return rob(root.left) + rob(root.right); } //二叉樹的公共祖先 public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { if(root==null){ return null; } if(root==p||root==q){ return root; } TreeNode leftTree = lowestCommonAncestor(root.left,p,q); //p||q null TreeNode rightTree = lowestCommonAncestor(root.right,p,q); //p||q null //3 if(leftTree!=null && rightTree!=null){ return root; } //左邊找到 else if (leftTree!=null ){ return leftTree; } //右邊找到 else if(rightTree!=null){ return rightTree; } //都沒找到的情況下 return null; } //二叉搜索樹,若他的左子樹不為空,左子樹上的所有節點都小於根節點, //如果他的右子樹不為空,右子樹上的所有節點都大於根節點 //最終他的中序排列都是有序結果 //輸入一棵二叉搜索樹,將該二叉搜索樹轉換成一個排序的雙向鏈表。 // 要求不能創建任何新的結點,只能調整樹中結點指針的指向。 TreeNode prev = null; public void ConvertChild(TreeNode pCur) { if(pCur == null) { return ; } ConvertChild(pCur.left); pCur.left = prev; if(prev != null) prev.right = pCur; prev = pCur; ConvertChild(pCur.right); } public TreeNode Convert(TreeNode pRootOfTree) { ConvertChild(pRootOfTree); TreeNode head = pRootOfTree; while(head != null&& head.left != null) { head = head.left; } return head; } //給定一個二叉樹的前序遍歷和中序遍歷,確定一棵二叉樹 /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public TreeNode build(int[] preorder, int[] inorder, int inbegin,int inend) { int preindex = 0; //當前樹 根本沒有左子樹或者是右子樹 if(inbegin > inend) { return null; } //根據前序遍歷,確定根節點 TreeNode root = new TreeNode(preorder[preindex]); //在中序遍歷里面 找到根節點的下標 int rootIndex = indexOfInorder(inorder,preorder[preindex],inbegin, inend); preindex++; root.left = build(preorder,inorder,inbegin,rootIndex-1); root.right = build(preorder,inorder,rootIndex+1,inend); return root; } public int indexOfInorder(int[] inorder,int val,int inbegin,int inend) { for(int i = inbegin;i <= inend;i++) { if(inorder[i] == val) { return i; } } return -1; } public TreeNode buildTree(int[] preorder, int[] inorder) { if(preorder.length == 0 || inorder.length == 0) { return null; } return build(preorder,inorder,0,inorder.length-1); } //根據一棵樹的中序遍歷與后序遍歷構造二叉樹 } class Test{ public static void main(String[] args) { Binarytree binarytree =new Binarytree(); Binarytree.TreeNode root =// binarytree.creatTesttree("ABC##DE#G##F###"); binarytree.creatTesttree("AB##C##"); binarytree.BTreeLevelOrder(root); System.out.println(); System.out.println("-----------------"); binarytree.binaryTreePrevOrder(root); } }