• 全部
...

二叉树的层次遍历 “朝闻道”知识分享大赛通知

菜菜菜攻城狮 2023-12-31 14:52:03

这是我参加“朝闻道”知识分享大赛的第五十四篇文章。

 

本文主要介绍一下二叉树的层次遍历。

首先先来说一下什么是层次遍历。

 层次遍历就是按照从左到右、从上到下的顺序对二叉树进行一个遍历,下面给出的二叉树的层次遍历的顺序是:ABCDEFG

二叉树的层次遍历主要是借助队列来完成的,主要思路就是A节点先入队,入队后再将A节点出队并获取到它的左右孩子入队,再将队头节点出队并获取它的左右孩子入队,依次执行直到队列为空。

 1.树结构的初始化

  1. //树结构
  2. typedef struct BiNode{
  3. char elem; //数据
  4. struct BiNode *lchild,*rchild; //父亲,左右孩子
  5. }BiNode,*BiTree;

通过先序递归的方法创建一颗二叉树

  1. void CreatBiTree(BiTree &T){
  2. char data;
  3. cin>>data;
  4. if(data=='#'){
  5. T=NULL;
  6. }else{
  7. T=new BiNode;
  8. T->elem=data;
  9. CreatBiTree(T->lchild);
  10. CreatBiTree(T->rchild);
  11. }
  12. }

2.队列的初始化及方法

  1. //队列节点
  2. typedef struct QNode{
  3. BiTree data;
  4. struct QNode *next;
  5. }QNode,*QueuePtr;
  6. //队列
  7. typedef struct Queue{
  8. QueuePtr front; //队头指针
  9. QueuePtr rear; //队尾指针
  10. }LQueue;
  1. //初始化队列
  2. void InitQueue(LQueue *Lq){
  3. Lq->front=Lq->rear=new QNode;
  4. Lq->front->next=nullptr;
  5. }
  6. //树节点入队
  7. void LqPush(LQueue *Lq,BiTree T){
  8. QNode *p=new QNode;
  9. p->data=T;
  10. p->next=nullptr;
  11. Lq->rear->next=p;
  12. Lq->rear=p;
  13. }
  14. //获取队头元素,并将队头元素后移
  15. BiTree LqPop(LQueue *Lq){
  16. if(Lq->front==Lq->rear){
  17. exit(0);
  18. }
  19. BiTree p=Lq->front->next->data;
  20. Lq->front=Lq->front->next;
  21. return p;
  22. }

3.按层次遍历二叉树

  1. //按层次遍历序列
  2. void LevelOrderTraverse(BiTree T){
  3. LQueue Lq;
  4. //判断树是否为空
  5. if(T==NULL){
  6. exit(0);
  7. }
  8. InitQueue(&Lq);
  9. LqPush(&Lq,T); //存入根节点
  10. //当队列不为空时
  11. while(Lq.front!=Lq.rear){
  12. //获取队头元素并且输出
  13. BiTree fro=LqPop(&Lq);
  14. cout<<fro->elem;
  15. if(fro->lchild){
  16. LqPush(&Lq,fro->lchild);
  17. }
  18. if(fro->rchild){
  19. LqPush(&Lq,fro->rchild);
  20. }
  21. }
  22. }

二叉树的递归遍历是比较简单的,也是比较好理解的,但是二叉树的非递归遍历就比较难理解了,接下来主要讨论一下非递归的中序遍历,并出具体实现。非递归实现树的遍历主要是借助了栈这一结构。接下来我们具体看看非递归遍历树是如何实现的。

 

2.非递归的中序遍历

非递归的中序遍历是从最下层的左子树开始,以左中右这种方式一层一层往上去遍历,所以我们先遍历节点若节点存在就将其入栈,再将访问其左孩子,直到遇到某个没有左孩子的节点就出栈访问该节点的右节点,若也为空就出栈,这时我们的栈就会指向这个出栈的节点的根节点,去去判断这个根节点有无右子树,这基本上就是一个循环过程了,我们只需要再树节点不为空或者栈不为空时让其一直循环便可。接下来是代码的实现。

  1. //栈
  2. typedef struct Stack{
  3. BiTree data;
  4. struct Stack *next;
  5. }Stack,*StackPtr;
  6. //有关栈的方法
  7. //初始化栈
  8. void InitStack(StackPtr &stack){
  9. stack=NULL;
  10. }
  11. //判断栈是否为空
  12. int isEmpty(StackPtr stack){
  13. if(stack==NULL){
  14. return 1;
  15. }else{
  16. return 0;
  17. }
  18. }
  19. //进栈
  20. void Push(StackPtr &stack,BiTree T){
  21. if(T==NULL){
  22. exit(0);
  23. }
  24. Stack *p=new Stack;
  25. p->data=T;
  26. p->next=stack;
  27. stack=p;
  28. }
  29. //出栈
  30. void Pop(StackPtr &stack,BiTree &q){
  31. if(isEmpty(stack)){
  32. exit(0);
  33. }
  34. q=stack->data;
  35. Stack *p=stack;
  36. stack=stack->next;
  37. delete p;
  38. }

 2.2通过非递归的中序遍历输出树的节点

  1. void InOrderTraversal(BiTree T){
  2. StackPtr S;
  3. InitStack(S);
  4. BiTree p=T;
  5. BiTree q; //用来存储弹出节点的根节点,需要借助其去到右子树
  6. while(p||!isEmpty(S)){
  7. if(p){
  8. Push(S,p);
  9. p=p->lchild;
  10. }else{
  11. Pop(S,q);
  12. cout<<q->elem;
  13. p=q->rchild;
  14. }
  15. }
  16. }

3.非递归的先序遍历

先序的非递归遍历就是,先遍历节点,若存在输出节点并入栈,并使指针指向其左孩子,若节点不存在就出栈,并访问栈顶节点的右孩子,直到栈为空且节点不存在时停止循环遍历即可。

  1. //通过非递归的先序遍历输出树的节点
  2. void PreOrderTraversalF(BiTree T){
  3. StackPtr S;
  4. InitStack(S);
  5. BiTree p=T;
  6. BiTree q; //用来存储弹出节点的根节点,需要借助其去到右子树
  7. while(p||!isEmpty(S)){
  8. if(p){
  9. Push(S,p);
  10. cout<<p->elem;
  11. p=p->lchild;
  12. }else{
  13. Pop(S,q);
  14. p=q->rchild;
  15. }
  16. }
  17. }

4.非递归的后序遍历

  1. void PostOrderTraversalF(BiTree T)
  2. {
  3. StackPtr S;
  4. InitStack(S);
  5. BiTree p=T;
  6. char Flag[MAXSIZE] = {'0'}; //用于标记该节点是否遍历右子树,遍历完了才可以将该节点输出
  7. while (p || !isEmpty(*S))
  8. {
  9. if (p)
  10. {
  11. Push(S, p);
  12. Flag[S->top] = '0'; //标志结点还未遍历右子树
  13. p = p->lchild;
  14. }
  15. else
  16. {
  17. while (Flag[S->top] == '1') {
  18. Pop(S, &p);
  19. cout<<p->elem;
  20. }
  21. if (S->top == -1) break;
  22. Pop(S, &p);
  23. Push(S, p);
  24. p = p->rchild;
  25. tag[S->top] = '1';
  26. }
  27. }
  28. }

 

 

...全文
给本帖投票
202 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

1,040

社区成员

发帖
与我相关
我的任务
社区描述
中南民族大学CSDN高校俱乐部聚焦校内IT技术爱好者,通过构建系统化的内容和运营体系,旨在将中南民族大学CSDN社区变成校内最大的技术交流沟通平台。
经验分享 高校 湖北省·武汉市
社区管理员
  • c_university_1575
  • WhiteGlint666
  • wzh_scuec
加入社区
社区公告

欢迎各位加入中南民族大学&&CSDN高校俱乐部社区(官方QQ群:908527260),成为CSDN高校俱乐部的成员具体步骤(必填),填写如下表单,表单链接如下:
人才储备数据库及线上礼品发放表单邀请人吴钟昊:https://ddz.red/CSDN
CSDN高校俱乐部是给大家提供技术分享交流的平台,会不定期的给大家分享CSDN方面的相关比赛以及活动或实习报名链接,希望大家一起努力加油!共同建设中南民族大学良好的技术知识分享社区。

注意:

1.社区成员不得在社区发布违反社会主义核心价值观的言论。

2.社区成员不得在社区内谈及政治敏感话题。

3.该社区为知识分享的平台,可以相互探讨、交流学习经验,尽量不在社区谈论其他无关话题。

试试用AI创作助手写篇文章吧

手机看
关注公众号

关注公众号

客服 返回
顶部