樹的三種遍歷(遞歸與非遞歸實現)

1:深度優先


1.1:前序遍歷

  1. Visit the root.
  2. Traverse the left subtree.
  3. Traverse the right subtree.
如下圖:
Pre-order: F, B, A, D, C, E, G, I, H
僞代碼:
preorder(node)
  if node == null then return
  visit(node)
  preorder(node.left) 
  preorder(node.right)
iterativePreorder(node)
  parentStack = empty stack
  parentStack.push(null)
  top =  node 
  while ( top != null )
      visit( top )
      if ( top.right != null ) 
          parentStack.push(top.right)
      if ( top.left != null ) 
          parentStack.push(top.left)
      top = parentStack.top();
      parentStack.pop();

1.2:中序遍歷

  1. Traverse the left subtree.
  2. Visit root.
  3. Traverse the right subtree.
In-order: A, B, C, D, E, F, G, H, I
僞代碼:
inorder(node)
  if node == null then return
  inorder(node.left)
  visit(node)
  inorder(node.right)
iterativeInorder(node)
  parentStack = empty stack
  while (not parentStack.isEmpty() or node ≠ null)
    if (node ≠ null)
      parentStack.push(node)
      node = node.left
    else
      node = parentStack.pop()
      visit(node)
      node = node.right

1.3:後序遍歷

  1. Traverse the left subtree.
  2. Traverse the right subtree.
  3. Visit the root.
Post-order: A, C, E, D, B, H, I, G, F
僞代碼
postorder(node)
  if node == null then return
  postorder(node.left)
  postorder(node.right)
  visit(node)
iterativePostorder(node)
  parentStack = empty stack  
  lastnodevisited = null 
  while (not parentStack.isEmpty() or node ≠ null)
    if (node ≠ null)
      parentStack.push(node)
      node = node.left
    else
      peeknode = parentStack.peek()
      if (peeknode.right ≠ null and lastnodevisited ≠ peeknode.right) 
        /* if right child exists AND traversing node from left child, move right */
        node = peeknode.right
      else
        parentStack.pop() 
        visit(peeknode)
        lastnodevisited = peeknode

1.4:java代碼實現三種遍歷

樹的結構是
                                            10
                                           /   \
                                          5     12
                                        /   \   
                                     4       7 
代碼中我主要解釋下讓我一直糾結的遞歸法了,總是對遞歸法執行的順序有疑惑。詳細可以看《Thinking In Algorithm》09.徹底理解遞歸

  1. public class Preorder{    
  2.     /*******************************遞歸法****************************/  
  3.     //遞歸前序遍歷        print:10,5,4,7,12  
  4.     public static void preorder(TNode node){  
  5.         if(node!=null){  
  6.             System.out.println(node.getValue()) ;  
  7.             preorder(node.getLeft()) ;  
  8.             preorder(node.getRight()) ;  
  9.         }  
  10.     }  
  11.     //遞歸中序遍歷        print: 4,5,7,10,12  
  12.     public static void inorder(TNode node){  
  13.         if(node!=null){  
  14.             inorder(node.getLeft()) ;  
  15.             System.out.println(node.getValue()) ;  
  16.             inorder(node.getRight()) ;  
  17.         }  
  18.     }  
  19.     //遞歸後序遍歷        print: 4,7,5,12,10  
  20.     public static void postorder(TNode node){  
  21.         if(node!=null){  
  22.             postorder(node.getLeft()) ;  
  23.             postorder(node.getRight()) ;  
  24.             System.out.println(node.getValue()) ;  
  25.         }  
  26.     }  
  27.       
  28.     /*******************************非遞歸*****************************/  
  29.     //非遞歸前序遍歷       print:10,5,4,7,12  
  30.     public static void iterativePreorder(TNode node){  
  31.         MyStack parentStack = new MyStack() ;  
  32.         parentStack.push(node) ;  
  33.         while(!parentStack.isEmpty()){  
  34.             TNode temp = parentStack.getFirst().getValue() ;  
  35.             System.out.println(temp.getValue()) ;  
  36.             parentStack.pop() ;  
  37.             if(temp.getRight()!=null){ parentStack.push(temp.getRight()) ;}  
  38.             if(temp.getLeft()!=null){ parentStack.push(temp.getLeft()) ;}  
  39.         }  
  40.     }  
  41.     //非遞歸中序遍歷       print: 4,5,7,10,12  
  42.     public static void iterativeInorder(TNode node){  
  43.         MyStack  mystack = new MyStack() ;  
  44.         while(!mystack.isEmpty()||node!=null){  
  45.             if(node!=null){  
  46.                 mystack.push(node) ;  
  47.                 node = node.getLeft() ;  
  48.             }else{  
  49.                 node = mystack.pop().getValue() ;  
  50.                 System.out.println(node.getValue()) ;  
  51.                 node = node.getRight() ;  
  52.             }  
  53.         }  
  54.     }  
  55.     //非遞歸後序遍歷       print: 4,7,5,12,10  
  56.     public static void iterativePostorder(TNode node){  
  57.         MyStack  mystack = new MyStack() ;  
  58.         TNode temp = null ;  
  59.         TNode peeknode = null ;  
  60.         while(!mystack.isEmpty()||node!=null){  
  61.             if(node!=null){  
  62.                 mystack.push(node) ;  
  63.                 node = node.getLeft() ;  
  64.             }else{  
  65.                 peeknode = mystack.getFirst().getValue() ;  
  66.                 if(peeknode.getRight()!=null&&temp!=peeknode.getRight()){  
  67.                     node = peeknode.getRight() ;  
  68.                 }else{  
  69.                     mystack.pop() ;  
  70.                     System.out.println(peeknode.getValue()) ;  
  71.                     temp = peeknode ;  
  72.                 }  
  73.             }  
  74.         }  
  75.     }  
  76.       
  77.     public static void main(String args[]){  
  78.         MyTree mytree = new MyTree() ;  
  79.         mytree.insert(10) ;  
  80.         mytree.insert(5);  
  81.         mytree.insert(12);  
  82.         mytree.insert(4);  
  83.         mytree.insert(7);  
  84.           
  85.         preorder(mytree.getRoot()) ;  
  86.         inorder(mytree.getRoot()) ;  
  87.         postorder(mytree.getRoot()) ;  
  88.           
  89.         iterativePreorder(mytree.getRoot()) ;  
  90.         iterativeInorder(mytree.getRoot()) ;  
  91.         iterativePostorder(mytree.getRoot()) ;  
  92.     }  
  93. }  
  94. /*****************二叉樹的實現****************/  
  95. class TNode{  
  96.     private int value ;  
  97.     private TNode left ;  
  98.     private TNode right ;  
  99.       
  100.     public TNode(int value){ this.value = value ;}  
  101.     public void setLeft(int value){ this.left = new TNode(value) ;}  
  102.     public void setRight(int value){ this.right = new TNode(value) ;}  
  103.     public TNode getLeft(){ return this.left ;}  
  104.     public TNode getRight(){ return this.right ;}  
  105.     public int getValue(){ return this.value ;}  
  106. }  
  107. class MyTree{  
  108.     private TNode root ;  
  109.       
  110.     public void setRoot(int value){ this.root = new TNode(value) ;}  
  111.     public TNode getRoot(){ return this.root ;}  
  112.     public void insert(int value){  
  113.         TNode x = this.root ;  
  114.         TNode y = null ;  
  115.         while(x!=null){  
  116.             y = x ;  
  117.             if(value<x.getValue()){ x = x.getLeft() ;}  
  118.             else{ x = x.getRight() ;}  
  119.         }  
  120.           
  121.         if(y == null){ setRoot(value) ;}  
  122.         else if(value<y.getValue())  
  123.         { y.setLeft(value) ;}  
  124.         else{ y.setRight(value) ;}  
  125.     }  
  126. }  
  127.   
  128. /*****************棧的實現****************/  
  129. class StackNode{    
  130.         public TNode item ;    
  131.         public StackNode next ;    
  132.           
  133.         public StackNode(){ ;}  
  134.         public StackNode(TNode item){ this.item = item ;}  
  135.         public TNode getValue(){ return item ;}    
  136. }    
  137. class MyStack{    
  138.     int N ; //size of myStack    
  139.     StackNode first ; // the top of stack    
  140.         
  141.         
  142.     //size of mystack    
  143.     public int size(){ return N ;}    
  144.         
  145.     //empty or not    
  146.     public boolean isEmpty(){ return N==0 ;}    
  147.       
  148.     public StackNode getFirst(){ return this.first ;}  
  149.         
  150.     public void push(TNode item){  
  151.         if(isEmpty()){  
  152.             first = new StackNode() ;    
  153.             first.item = item;    
  154.             N++;   
  155.         }else{  
  156.             StackNode oldfirst = first;    
  157.             first = new StackNode() ;    
  158.             first.item = item;    
  159.             first.next = oldfirst;    
  160.             N++;   
  161.         }  
  162.           
  163.     }  
  164.     public StackNode pop(){  
  165.         StackNode top = first ;  
  166.         first = first.next;            // delete first node    
  167.         N--;    
  168.         return top ;  
  169.     }  
  170. }  


2.廣度遍歷

廣度遍歷比較簡單,就是層次遍歷
                
僞代碼
levelorder(root)
  q = empty queue
  q.enqueue(root)
  while not q.empty do
    node := q.dequeue()
    visit(node)
    if node.left ≠ null then
      q.enqueue(node.left)
    if node.right ≠ null then
      q.enqueue(node.right)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章