深度優先和廣度優先比較


區別:

 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);


    }
}

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM