二叉树的前序,中序,后序,层序遍历(递归,非递归双版本)

二叉树结点的表示:

采用链表的存储方式,设有数据域和左右孩子指针

代码实现:

typedef struct BiNode{
  ElemType data;
  struct BiNode *lchild,*rchild;    //左孩子,右孩子
}BiNode,*BiTree;

 二叉树的建立:

前序遍历输入结点

代码实现:

//建立二叉树
void CreateTree(BiTree &T){
  ElemType c;
  scanf("%c",&c);
  if(c=='#'){
    T=NULL;
    return;
  }
  else{
    T=(BiTree)malloc(sizeof(BiNode));    //开辟动态空间
    T->data=c;
    CreateTree(T->lchild);
    CreateTree(T->rchild);
  }
}

 前序遍历:

先输出根结点,依次遍历左子树和右子树

递归版本容易理解,在非递归版本中借用栈的特性来实现,思路是从根结点开始有左孩子就让左孩子进栈,之后跳出循环

如果栈不空输出栈顶元素,紧接着当前节点指向其右孩子,在返回循环让所有左孩子进栈

代码实现:

//先根递归遍历
void PreOrder(BiTree T){
  if(T){
    printf("%c ",T->data);
    PreOrder(T->lchild);
    PreOrder(T->rchild);
  }
}
//先根非递归遍历
void FPreOrder(BiTree T){
  stack<BiTree> s;
  BiTree cur=T;
  while(cur||!s.empty()){      //树不空或栈不空
    while(cur){                //从根节点一直往下遍历当前结点的左孩子,没有时跳出
      cout<<cur->data<<" ";    //输出根节点
      s.push(cur);             //同时入栈
      cur=cur->lchild;         //指向当前结点的左孩子
    }
    if(!s.empty()){            
      cur=s.top();             //当前结点指向栈顶元素
      s.pop();                 //出栈
      cur=cur->rchild;         //寻找其右孩子
    }
  }
}

 中序遍历:

先遍左子树,再根结点,最后右子树

在非递归版本中思想同先序遍历的相同,只是注意结点数据的输出位置不同,其他的都一样

代码实现:

void InOrder(BiTree T){
  if(T){
    InOrder(T->lchild);
    printf("%c ",T->data);
    InOrder(T->rchild);
  }
}
void FInOrder(BiTree T){
  stack<BiTree> s;
  BiTree cur=T;
  while(cur||!s.empty()){    
    while(cur){              //从根节点一直往下遍历当前节点的左孩子,没有时跳出  
      s.push(cur);             
      cur=cur->lchild;     
    }
    if(!s.empty()){          
      cur=s.top();
      cout<<cur->data<<" ";  
      s.pop();
      cur=cur->rchild;
    }
  }
}

 后序遍历:

先左子树,再右子树,最后根节点

在非递归版本中,刚开始从根节点开始有左孩子就让左孩子进栈,否则右孩子进栈,然后令当前结点指向栈顶元素,输出对应的数据后出栈,若当前结点是此时栈顶元素的左孩子,则让当前结点指向其右孩子,实现左右中的遍历顺序,若不是,证明当前结点是此时栈顶元素的右孩子,使当前节点为NULL,在下一次循环中直接输出双亲的数据

代码实现:

void PostOrder(BiTree T){
  if(T){
    PostOrder(T->lchild);
    PostOrder(T->rchild);
    printf("%c ",T->data);
  }
}
void FPostOrder(BiTree T){
  stack<BiTree> s;
  BiTree cur=T;
  while(cur||!s.empty()){
    while(cur){
      s.push(cur);
      cur=cur->lchild?cur->lchild:cur->rchild;  //左孩子先进,右孩子后进
    }
    cur=s.top();
    cout<<cur->data<<" ";
    s.pop();
    if(!s.empty()&&cur==(s.top())->lchild)      
      cur=(s.top())->rchild;
    else
      cur=NULL;
  }
}

 层序遍历:

即从上到下,从左到右依次输出元素值

很明显将二叉树中的元素按照对应顺序放入队列,然后输出队列里的值就行

代码实现:

void SeqOrder(BiTree T){
  queue<BiTree> q;
  if(T){
    q.push(T);    //根节点入队
  }
  while(!q.empty()){
    cout<<q.front()->data<<" ";    //输出队头元素
    if(q.front()->lchild){     
      q.push(q.front()->lchild);   //左孩子入队
    }
    if(q.front()->rchild){
      q.push(q.front()->rchild);   //右孩子入队
    }
    q.pop();                       //输出过的元素对应结点出队
  }
}

 完整代码:

#include<iostream>
#include<cstdio>
#include<queue>
#include<stack>
#include<cstdlib>
using namespace std;
typedef char ElemType;    //自定义结点数据类型
//建立二叉链表
typedef struct BiNode{
  ElemType data;
  struct BiNode *lchild,*rchild;    //左孩子,右孩子
}BiNode,*BiTree;
//建立二叉树
void CreateTree(BiTree &T){
  ElemType c;
  scanf("%c",&c);
  if(c=='#'){
    T=NULL;
    return;
  }
  else{
    T=(BiTree)malloc(sizeof(BiNode));    //开辟动态空间
    T->data=c;
    CreateTree(T->lchild);
    CreateTree(T->rchild);
  }
}
//先根递归遍历
void PreOrder(BiTree T){
  if(T){
    printf("%c ",T->data);
    PreOrder(T->lchild);
    PreOrder(T->rchild);
  }
}
//先根非递归遍历
void FPreOrder(BiTree T){
  stack<BiTree> s;
  BiTree cur=T;
  while(cur||!s.empty()){      //树不空或栈不空
    while(cur){                //从根节点一直往下遍历当前结点的左孩子,没有时跳出
      cout<<cur->data<<" ";    //输出根节点
      s.push(cur);             //同时入栈
      cur=cur->lchild;         //指向当前结点的左孩子
    }
    if(!s.empty()){            
      cur=s.top();             //当前结点指向栈顶元素
      s.pop();                 //出栈
      cur=cur->rchild;         //寻找其右孩子
    }
  }
}
void InOrder(BiTree T){
  if(T){
    InOrder(T->lchild);
    printf("%c ",T->data);
    InOrder(T->rchild);
  }
}
void FInOrder(BiTree T){
  stack<BiTree> s;
  BiTree cur=T;
  while(cur||!s.empty()){    
    while(cur){              //从根节点一直往下遍历当前节点的左孩子,没有时跳出  
      s.push(cur);             
      cur=cur->lchild;     
    }
    if(!s.empty()){          
      cur=s.top();
      cout<<cur->data<<" ";  
      s.pop();
      cur=cur->rchild;
    }
  }
}
void PostOrder(BiTree T){
  if(T){
    PostOrder(T->lchild);
    PostOrder(T->rchild);
    printf("%c ",T->data);
  }
}
void FPostOrder(BiTree T){
  stack<BiTree> s;
  BiTree cur=T;
  while(cur||!s.empty()){
    while(cur){
      s.push(cur);
      cur=cur->lchild?cur->lchild:cur->rchild;  //左孩子先进,右孩子后进
    }
    cur=s.top();
    cout<<cur->data<<" ";
    s.pop();
    if(!s.empty()&&cur==(s.top())->lchild)      
      cur=(s.top())->rchild;
    else
      cur=NULL;
  }
}
void SeqOrder(BiTree T){
  queue<BiTree> q;
  if(T){
    q.push(T);    //根节点入队
  }
  while(!q.empty()){
    cout<<q.front()->data<<" ";    //输出队头元素
    if(q.front()->lchild){     
      q.push(q.front()->lchild);   //左孩子入队
    }
    if(q.front()->rchild){
      q.push(q.front()->rchild);   //右孩子入队
    }
    q.pop();                       //输出过的元素对应结点出队
  }
}
int main(){
  BiTree T=NULL;
  //printf("前序遍历输入结点:\n");
  CreateTree(T);
  //printf("前序遍历:\n");
  PreOrder(T);
  cout<<endl;
  FPreOrder(T);
  cout<<endl;
  //printf("中序遍历:\n");
  InOrder(T);
  cout<<endl;
  FInOrder(T);
  cout<<endl;
  //printf("后序遍历:\n");
  PostOrder(T);
  cout<<endl;
  FPostOrder(T);
  cout<<endl;
  //printf("层序遍历:\n");
  SeqOrder(T);
  cout<<endl;
  return 0;
}

运行结果示例:

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值