现在的位置: 首页 > 综合 > 正文

树(二)二叉树递归和非递归遍历

2018年11月07日 ⁄ 综合 ⁄ 共 4683字 ⁄ 字号 评论关闭

1、递归遍历

// 先序遍历(递归实现)-------------------------------------------------------------
 	  /*
	  1. Visit the node.
	  1. Call itself to traverse the node’s left subtree.
      3. Call itself to traverse the node’s right subtree.
	  4. base case: there is no node
	  */
   private void preOrder(Node localRoot){
      if(localRoot != null)
         {
         visit(localRoot);       // System.out.print(localRoot.iData + " ");
         preOrder(localRoot.leftChild);
         preOrder(localRoot.rightChild);
         }
      }
// 中序遍历(递归实现)-------------------------------------------------------------
   private void inOrder(Node localRoot){
      if(localRoot != null)
         {
         inOrder(localRoot.leftChild);
         visit(localRoot);       //System.out.print(localRoot.iData + " ");
         inOrder(localRoot.rightChild);
         }
      }
// 后序遍历(递归实现)-------------------------------------------------------------
   private void postOrder(Node localRoot){
      if(localRoot != null)
         {
         postOrder(localRoot.leftChild);
         postOrder(localRoot.rightChild);
         visit(localRoot);       //System.out.print(localRoot.iData + " ");
         }
      }
// -------------------------------------------------------------

2、非递归遍历

总体思想是:因为递归的本质是用栈实现的,所以写出非递归的形式要用到栈。入栈的顺序与访问的顺序相反,如中序遍历访问顺序是left,current,right,所以入栈的顺序相反是right,current,left
steo0:初始化当前节点current
step1:初始化栈
step3:出栈,并访问
Note:中序遍历和后序遍历需要先判断bPushed为true时访问
step2:入栈
循环结束条件是:栈为空

//算法框架 pushNode是入栈的方式
public void templet(Node root){
  //special case
  if(root==null)
   return;
   
  //inital current node
  Node current=root;
  
  //initial stack
  Stack s=new Stack();
  pushNode(current,s);
  
  //loop: base case is stack is empty
  while( !s.empty() ){
     //pop
	 current=s.pop();
	 
	 //visit or push
  }//end while  
}//end templet()

前序遍历(即深度优先搜索)

//current left right 
//step1:push in stack 
push current's right child
push current's left child
visit current node
//step2:pop off stack
//step3: loop step1-step2

private void pushPreOrderNode(Node current, Stack s){
	   Node leftChild=current.leftChild;
	   Node rightChild=curret.rightChild;
	     
	   if(rightChild!=null)    //push rightChild
	      s.push(rightChild);
	   if(leftChild!=null)     //push leftChild
	      s.push(leftChild);
	   visit(current);        //current always first visit in preOrder  
}//end pushPreOrderNode()

public void preOrder(Node root){
    //special case
	if(root==null)
	  return ;
	
	//initial current node
	Node current=root;
	//inintial stack
	Stack s=new Stack();
	pushPreOrderNode(current,s);
	
	//base case:stack is empty
	while( !s.empty() ){
	  //pop
	  current=s.pop();
	  //push
	  pushPreOrderNode(current,s);
	}//end while
}//end preOrder()

中序遍历

left,current,right

public void inOrder( Node root){
   //special case
   if(root==null)
       return;
	   
	Node current=root;
	//initial stack
	Stack s=new Stack();
	pushInOrderNode(current,s);
	
	//pop and visit
	while( !s.empty() ){
		 current=s.pop();
		 if(current.bPushed)
			visit(current);
		 else
			pushInOrderNode(current,s);
	}//end while
}//end postOrder()

private void pushInOrderNode(Node current,Stack s){
   Node leftChild=current.leftChild;
   Node rightChild=curret.rightChild;
   
   if(rightChild!=null){   //push rightChild
	  s.push(rightChild);
	  rightChild.bPushed=false;
   }//end if
   
   s.push(current);        //push current
   
   if(leftChild!=null){    //push leftChild
	  s.push(leftChild);
	  leftChild.bPushed=false;
   }//end if
	  
   //set flag, ture present current's left and right has both pushed
   current.bPushed=true;
   }//end if
}//end pushInOrderNode()

后序遍历

left right current
step1:初始化栈
按照step2初始化栈
step2:入栈
入栈顺序:current,right,left
如果current的中左右节点都入栈了,将current标识为true;
将入栈的左右节点标识初始化为false
step3:出栈
出栈节点设置为current,
如果current标识为ture,访问之;如果为false,做step2步骤
step4:重复step2&step3

public void postOrder( Node root){
   //special case
   if(root==null)
       return;
	   
	Node current=root;
	
	//initial stack
	Stack s=new Stack();
	pushPostOrderNode(current,s);
	
	//pop and visit
	while( !s.empty() ){
	     current=s.pop();
		 if(current.bPushed)
		    visit(current);
		 else
		    pushPostOrderNode(current,s);
	}//end while
}//end postOrder()

// 左右子树尚未入栈,则依次将 根节点,右节点,左节点 入栈
private void  pushPostOrderNode(Node current, Stack s){
   Node leftChild=current.leftChild;
   Node rightChild=curret.rightChild;
   
   s.push(current);        //push current
   if(rightChild!=null){   //push rightChild
	  s.push(rightChild);
	  rightChild.bPushed=false;
   }//end if
   if(leftChild!=null){    //push leftChild
	  s.push(leftChild);
	  rightChild.bPushed=false;
   }//end if
	  
   //set flag, ture present current's left and right has both pushed
   current.bPushed=true;	
}//end pushPostOrderNode()

3 深度优先搜索和层次遍历(广度优先搜索)

先序遍历即深度优先搜索,层次遍历即广度优先搜索
// -------------------------------------------------------------
/*
二叉树的深度优先搜索即先序遍历,用栈实现(非递归实现)
*/

// -------------------------------------------------------------
/*
层次搜索,即广度优先搜索
step1:specail case
root==null;
step2:initial current
current=root;
step3:initial queue
step4:remove node in queue, and visit the current node
step5:add node in queue
step6:loop step4 and step5
base case: queue is empty
*/

public void gfs(Noode root){
  //step1:specail case
  if(root==null)
    return ;
  
  //step2:initial current
  Node current=root;
  
  //step3:initial queue
  Queue q=new Queue();
  q.add(current);
  
  //step6:loop step4 and step5
  //base case: queue is empty
  while( !q.empty() ){
    //step4:remove node in queue
	current=q.remove();
	visit(current);
	
	Node leftChild=current.leftChild;
	Node rightChild=curret.rightChild;
	
	//step5:add node in queue
	if(leftChild!=null)
	   q.add(leftChild);
	if(rightChild!=null)
	   q.add(rightChild);
  }//end while 
}//gfs()

抱歉!评论已关闭.