c++ 结构体遍历_【数据结构14】别眨眼!非递归方式实现二叉树的遍历!!!

5b48c5aebc514258d431aea54d47f154.gif

不用递归,二叉树怎么遍历?

我们知道,二叉树,总共有四种遍历方法: 先序遍历中序遍历后序遍历层次遍历
在前面我们有讲到这四种遍历方法的递归方式实现,
什么?没讲?
看这里:【数据结构-13】二叉树的遍历
害,末尾也给了链接,可以翻到后面看噢。
那么,非递归算法是咋写的?
老规矩,我们需要先定义好树的基本结构,
这里我们用一个链表来存储树。
方法呢,就是用的C语言的结构体。
关于结构体,可以看这里:【数据结构+C语言-7】当C语言遇上数据结构
#define MaxSize 100typedef char ElemType;typedef struct node {    ElemType data;      //数据元素  struct node *lchild;  //指向左孩子节点  struct node *rchild;  //指向右孩子节点} BTNode;

定义好了树,我们就要开始遍历了。

且!!!慢!!!

先来一段大升格!

31bdbb4001b7c035de2263ccadfb983f.gif

哦不好意思,走错片场了。

遍历嘛,而且这次又用的是非递归方式,那首先我们就要搞啥?

对,要完成递归算法到非递归算法的转变,

重要的就是工具人

在数据结构里面,有两个非常著名的工具人,

一个老哥,叫做

另一个老哥,叫做队列

我们先来定义一个栈。

typedef struct {  BTNode *data[MaxSize];      //存放栈中的数据元素    int top;  //存放栈顶指针,即栈顶元素在data数组中的下标} SqStack;

既然有了栈,那肯定要有栈的各种操作对吧,

初始化一个栈:

void InitStack(SqStack *&s)      //初始化栈{  //分配一个是顺序栈空间,首地址存放在s中   s=(SqStack *)malloc(sizeof(SqStack));   s->top=-1;            //栈顶指针置为-1}

销毁一个栈:

void DestroyStack(SqStack *&s)    //销毁栈{  free(s);}

判断栈空:

bool StackEmpty(SqStack *s)      //判断栈是否为空{  return(s->top==-1);}

元素入栈:

bool Push(SqStack *&s,BTNode *e)  //进栈{  if (s->top==MaxSize-1)      //栈满的情况,即栈上溢出    return false;  s->top++;            //栈顶指针增1  s->data[s->top]=e;        //元素e放在栈顶指针处  return true;}

元素出栈:

bool Pop(SqStack *&s,BTNode *&e)  //出栈{  if (s->top==-1)          //栈为空的情况,即栈下溢出    return false;  e=s->data[s->top];        //取栈顶指针元素的元素  s->top--;            //栈顶指针减1  return true;}

取栈顶元素:

bool GetTop(SqStack *s,BTNode *&e)  //取栈顶元素{  if (s->top==-1)          //栈为空的情况,即栈下溢出    return false;  e=s->data[s->top];        //取栈顶元素  return true;}

到这里,
我们的工具人就差不多安排好了,
可以开始搞遍历了。
开搞!

先来一段先序遍历:

void PreOrder(BTNode *b)      //先序非递归遍历算法{  BTNode *p;  SqStack *st;          //定义一个顺序栈指针st  InitStack(st);          //初始化栈st  Push(st,b);          //根节点进栈  while (!StackEmpty(st))    //栈不为空时循环  {    Pop(st,p);        //退栈节点p并访问它    printf("%c ",p->data);  //访问节点p    if (p->rchild!=NULL)  //有右孩子时将其进栈      Push(st,p->rchild);    if (p->lchild!=NULL)  //有左孩子时将其进栈      Push(st,p->lchild);  }  printf("\n");  DestroyStack(st);        //销毁栈}

再来一段中序遍历:

void InOrder(BTNode *b)        //中序非递归遍历算法{  BTNode *p;  SqStack *st;            //定义一个顺序栈指针st  InitStack(st);            //初始化栈st  if (b!=NULL)  {    p=b;    while (!StackEmpty(st) || p!=NULL)    {      while (p!=NULL)        //扫描节点p的所有左下节点并进栈      {        Push(st,p);        //节点p进栈        p=p->lchild;      //移动到左孩子      }      if (!StackEmpty(st))    //若栈不空      {        Pop(st,p);        //出栈节点p        printf("%c ",p->data);  //访问节点p        p=p->rchild;      //转向处理其右子树      }    }    printf("\n");  }  DestroyStack(st);        //销毁栈}

最后来一段后序遍历:

void PostOrder(BTNode *b)        //后序非递归遍历算法{  BTNode *p,*r;  bool flag;  SqStack *st;            //定义一个顺序栈指针st  InitStack(st);            //初始化栈st  p=b;  do  {    while (p!=NULL)          //扫描节点p的所有左下节点并进栈    {      Push(st,p);          //节点p进栈      p=p->lchild;        //移动到左孩子    }    r=NULL;              //r指向刚刚访问的节点,初始时为空    flag=true;            //flag为真表示正在处理栈顶节点    while (!StackEmpty(st) && flag)    {      GetTop(st,p);        //取出当前的栈顶节点p      if (p->rchild==r)      //若节点p的右孩子为空或者为刚刚访问过的节点        {        printf("%c ",p->data);  //访问节点p        Pop(st,p);        r=p;          //r指向刚访问过的节点      }      else      {          p=p->rchild;      //转向处理其右子树        flag=false;        //表示当前不是处理栈顶节点      }    }  } while (!StackEmpty(st));      //栈不空循环  printf("\n");  DestroyStack(st);        //销毁栈}

这三个里面,后序遍历是最麻烦的,因为我们需要去记录我之前访问了哪个节点,来作为额外的判断条件。

完事。

往期回顾:

【数据结构+C语言-7】当C语言遇上数据结构

【数据结构+C语言-8】磨 刀 霍 霍

【数据结构+C语言-9】怎么操作一个链表?

【数据结构-13】二叉树的遍历

b1f40d514eff5676f06f773625454407.png

如果觉得有用,不点个再看么少年?↓
[]~( ̄▽ ̄)~*

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值