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

二叉树的遍历方法(递归,非递归)

2013年10月26日 ⁄ 综合 ⁄ 共 2123字 ⁄ 字号 评论关闭

//4.4 二叉树的遍历方法
#define n0 100
struct node
{
 int data;
 int llink,rlink;
};

node tree[n0+1];
int root;  //树的根节点位置

//递归方式实现前序,中序,后序遍历
void preorder(int p)
{
 if(!p)
 {//如果根节点不为空
  cout<<tree[p].data;
  preorder(tree[p].llink);
  preorder(tree[p].rlink);
 }
}

void inorder(int p)
{
 if(!p)
 {//如果根节点不为空
  inorder(tree[p].llink);
  cout<<tree[p].data;
  inorder(tree[p].rlink);
 }
}

void postorder(int p)
{
 if(!p)
 {//如果根节点不为空
  postorder(tree[p].llink);
  postorder(tree[p].rlink);
  cout<<tree[p].data;
 }
}

//非递归算法的前序,中序,后序遍历
//前序列的算法思想 :从二叉树的根节点开始,令指针变量P指向根节点,访问当前节点p,并将p压入栈中。
//然后令p指向当前指向节点的左孩子节点。若p不为空,继续访问当前节点p,并将p压入栈中。如此反复直到p为空
//从栈中弹出栈顶元素赋给指针变量p,并令p指向它的右孩子节点,重复上述过程,当p为空,并且栈也为空时候,遍历结束。
void preorder()
{
 int s[n0+1]; //栈
 int t;       //栈指针
 int p = root;//树指针

 while(p||t)
 {//当p不为空或者栈不为空时
  if(p)
  {//当期指针不为空时候
   cout<<tree[p].data; //访问当前节点
   s[++t] = p;   //当前地址入栈
   p = tree[p].llink;  //p指向p的左孩子
  }
  else
  {//如果p指向的p的左孩子为空,就是没有左孩子
   p = s[t--];//p返回到它的父亲节点
   p = tree[p].rlink; //p指向它的父亲节点的右孩子
  }

 }
}

//中序算法:和前序算法基本上一致,但是数据访问在出栈的时候
//前序列的算法思想 :从二叉树的根节点开始,令指针变量p指向根节点,访问当前节点p,并将p压入栈中。
//然后令p指向当前指向节点的左孩子节点。若p不为空,继续访问当前节点p,并将p压入栈中。如此反复直到p为空
//从栈中弹出栈顶元素赋给指针变量p,并令p指向它的右孩子节点,重复上述过程,当p为空,并且栈也为空时候,遍历结束。

void preorder()
{
 int s[n0+1]; //栈
 int t;       //栈指针
 int p = root;//树指针
 
 while(p||t)
 {//当p不为空或者栈不为空时
  if(p)
  {//当期指针不为空时候
   s[++t] = p;   //当前地址入栈
   p = tree[p].llink;  //p指向p的左孩子
  }
  else
  {//如果p指向的p的左孩子为空,就是没有左孩子
   p = s[t--];//p返回到它的父亲节点
   cout<<tree[p].data; //访问当前节点
   p = tree[p].rlink; //p指向它的父亲节点的右孩子
  }
  
 }
}

//后序遍历
//算法思路:当遇到非空的二叉树时候,首先将根节点地址和该节点的“右子树没有遍历”标记压入栈,然后沿
//左子数下降去遍历根节点的左子树,当遇到空二叉树时候,也就是这个节点没有左子树了,弹出栈顶元素,
//取得这个节点根节点的位置和,该根节点的右子树是否已经遍历的标记。
//1如果右子树已经遍历,就访问这个根节点。
//2如果右子树没有遍历,就把这个根节点的地址和这个根节点的“右子树已经遍历”的标记,压入栈中。然后沿
//右子树去遍历这个根节点的右子树。
//s[t] > 0 :此节点右子树没有遍历
//s[t] < 0 : 此节点右子树已经遍历

void postorder()
{
 int s[n0+1]; //栈
 int t = 0;   //栈指针
 int p = root;//p指向当前节点

 while(p||t)
 {//当当前指针不为空 或者 栈不为空的时候
  if(p)
  {//如果当前指针不为空
   s[++t] = p ;//同时p>0表示这个节点的右孩子还没有被遍历
   p = tree[p].llink; //沿着左孩子向下遍历
  }
  else
  {//如果当期指针为空了,表示栈顶节点的左孩子为空
   if(s[t]<0)
   {//如果这个栈顶节点的右孩子被访问过了
    p = -s[t--];  //出栈,得到当前节点的父亲节点的地址
    cout<<tree[p].data; //访问根节点
   }
   else
   {//如果栈顶节点的右孩子没有被访问过
    s[t] = -s[t];  //表示栈顶节点的右孩子已经被遍历过了
    p = s[t]; //
    p = tree[s[t]]->rlink;
   }
  }

 }
}

抱歉!评论已关闭.