遍历二叉树递归算法与非递归算法

 

二叉树的3种遍历方式前序,后序和中序,先访问根节点就是前序,类似的,最后访问根节点就是后序。

 

typedef int ElemType; 

typedef struct treeT
{
    ElemType key;
    struct treeT* left;
    struct treeT* right;
}treeT, *pTreeT;

 

前序遍历

  前序遍历(DLR)
  前序遍历也叫做先根遍历,可记做根左右。
  前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。在遍历左、右子树时,仍然先访问根结点,然后遍历左子树,最后遍历右子树。
  若二叉树为空则结束返回,否则:
  (1)访问根结点
  (2)前序遍历左子树
  (3)前序遍历右子树
  注意的是:遍历左右子树时仍然采用前序遍历方法。
 

前序遍历的递归算法

  1. void preOrder(TNode* root)
  2. {
  3.     if (root != NULL)
  4.     {
  5.         Visit(root);
  6.         preOrder(root->left);
  7.         preOrder(root->right);
  8.     }
  9. }

前序非递归算法
【思路】
假设:T是要遍历树的根指针,若T != NULL
对于非递归算法,引入栈模拟递归工作栈,初始时栈为空。
问题:如何用栈来保存信息,使得在先序遍历过左子树后,能利用栈顶信息获取T的右子树的根指针?
方法1:访问T->data后,将T入栈,遍历左子树;遍历完左子树返回时,栈顶元素应为T,出栈,再前序遍历T的右子树。
方法2:访问T->data后,将T->rchild入栈,遍历左子树;遍历完左子树返回时,栈顶元素应为T->rchild,出栈,遍历以该指针为根的子树。

 伪代码

【算法1】
void    PreOrder(BiTree T, Status (*Visit ) (ElemType e))

{    

// 基于方法一,当型循环
InitStack(S);
while ( T!=NULL || !StackEmpty(S)){
while ( T != NULL ){
Visit(T->data) ;
Push(S,T);
T = T->lchild;
}
if( !StackEmpty(S) ){
Pop(S,T);
T = T->rchild;
}
}
}
【算法2】
void    PreOrder(BiTree T, Status ( *Visit ) (ElemType e))

{   

 // 基于方法二,当型循环
InitStack(S);
while ( T!=NULL || !StackEmpty(S) ){
while ( T != NULL ){
Visit(T->data);
Push(S, T->rchild);
T = T->lchild;
}
if ( !StackEmpty(S) ){
Pop(S,T);
}
}
}

非伪代码实现以后再整,现在头有点晕

 

  

中序遍历

  中序遍历(LDR)
  中序遍历也叫做中根遍历,可记做左根右。
  中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树。在遍历左、右子树时,仍然先遍历左子树,再访问根结点,最后遍历右子树。即:
  若二叉树为空则结束返回,否则:
  (1)中序遍历左子树
  (2)访问根结点
  (3)中序遍历右子树。
  注意的是:遍历左右子树时仍然采用中序遍历方法。
 
后序遍历
后序遍历是二叉树遍历的一种。后序遍历指在访问根结点、遍历左子树与遍历右子树三者中,首先遍历左子树,然后遍历右子树,最后遍历访问根结点,在遍历左、右子树时,仍然先遍历左子树,然后遍历右子树,最后遍历根结点。后序遍历有递归算法和非递归算法两种。
  
递归算法,算法描述:
  (1)若二叉树为空,结束
  (2)后序遍历左子树
  (3)后序遍历右子树
  (4)访问根结点
  伪代码
  PROCEDURE POSTRAV(BT)
  IF BT<>0 THEN
  {
  POSTRAV(L(BT))
  POSTRAV(R(BT))
  OUTPUT V(BT)
  }
  RETURN
  c语言描述
  struct btnode
  {
  int d;
  struct btnode *lchild;
  struct btnode *rchild;
  };
  void postrav(struct btnode *bt)
  {
  if(bt!=NULL)
  {
  postrav(bt->lchild);
  postrav(bt->rchild);
  printf("%d ",bt->d);
  }
  }
非递归算法,算法1(c语言描述):
  void postrav1(struct btnode *bt)
  {
  struct btnode *p;
  struct
  {
  struct btnode *pt;
  int tag;
  }st[MaxSize];
  }
  int top=-1;
  top++;
  st[top].pt=bt;
  st[top].tag=1;
  while(top>-1) /* 不为空*/
  {
  if(st[top].tag==1) /*不能直接访问的情况*/
  {
  p=st[top].pt;
  top--;
  if(p!=NULL)
  {
  top++; /*根结点*/
  st[top].pt=p;
  st[top].tag=0;
  top++; /*右孩子结点*/
  st[top].pt=p->p->rchild;
  st[top].tag=1;
  top++; /*左孩子结点*/
  st[top].pt=p->lchild;
  st[top].tag=1;
  }
  }
  if(st[top].tag==0) /*直接访问的情况*/
  {
  printf("%d ",st[top].pt->d);
  top--;
  }
  }
  }
  算法2:
  void postrav2(struct btnode *bt)
  {
  struct btnode *st[MaxSize],*p;
  int flag,top=-1;
  if(bt!=NULL)
  {
  do
  {
  while(bt!=NULL)
  {
  top++;
  st[top]=bt;
  bt=bt->lchild;
  }
  p=NULL;
  flag=1;
  while(top!=-1 && flag)
  {
  bt=st[top];
  if(bt->rchild==p)
  {
  printf("%d ",bt->d);
  top--;
  p=bt;
  }
  else
  {
  bt=bt->rchild;
  flag=0;
  }
  }
  }while(top!=-1)
  printf("/n");
  }
  }

你可能感兴趣的:(算法,struct,null,语言,BT,output)