创建二叉树——少见的方法(下篇)

创建二叉树——少见的方法(下篇)

上篇我们详细介绍了先序遍历创建二叉树,上篇:
https://editor.csdn.net/md/?articleId=106159923
其在输入端必须按照先序遍历序列中的顺序输入才能完成二叉树的建立,上篇博客代码运行界面图片:
在这里插入图片描述
那么如果我们想较为方便地一层一层输入各结点值,来完成一棵二叉树的建立,是否也可以成功呢?例如:
在这里插入图片描述
我们想通过输入“ABCDE”来完成一颗二叉树的建立
注:在输入端应该输入“ABCDE######“,前两个#代表叶子结点C的左孩子、右孩子,后四个#代表叶子结点D和E的左孩子、右孩子
对#作用不清楚的翻看上篇博客。

分析过程

这一思路中需要用到队列,原因:例如当我们依照顺序完成了前三个结点“ABC”的建立后,需要开始D的建立,而D和B相关(D是B的左孩子),所以我们需要用到前面的结点。对这一点还是不太理解的结合着下面代码来理解。
代码实现

//实现按层次创建二叉树
void create(BTree &root,char *ch,circl cl)
{
 BTNode *q;//用于接收出队的结点元素
 if(*ch=='#')//第一个字符为#时,表示为空树,则直接置为NULL,后续无需再进行
  root=NULL;
 else//不为空树时
 {
  root=(BTree)malloc(sizeof(BTNode));//事先给根结点分配空间
  (*root).data=*ch;//赋值
  cl.data[++cl.rear]=root; //根结点入队列
  while(cl.front!=cl.rear)//循环中止的条件是队列为空
  {
   q=cl.data[++cl.front];//对头元素出队
   ++ch;//-----------------------------------------分析当前结点的左孩子
   (*q).lchild=(BTree)malloc(sizeof(BTNode));//使用前一定不要忘了给其分配空间
   if(*ch=='#')
    (*q).lchild=NULL;
   else
   {
    (*(*q).lchild).data=*ch;
    cl.data[++cl.rear]=(*q).lchild;//不空时才入队
   }
   ++ch;//-----------------------------------------分析当前结点的右孩子
   (*q).rchild=(BTree)malloc(sizeof(BTNode));//使用前一定不要忘了给其分配空间
   if(*ch=='#')
    (*q).rchild=NULL;
   else
   {
    (*(*q).rchild).data=*ch;
    cl.data[++cl.rear]=(*q).rchild;//不空时入队
   }
  }
 }
}

运行结果
在这里插入图片描述
:为了验证是否创建成功,我输出了三种遍历方式下的序列。同也可以和上篇“先序遍历创建二叉树”的运行结果作对比分析(是一致的)

至此,就完成了依层次创建二叉树的工作
可以看出还是“先序遍历创建二叉树”更为直观简单,且代码易读易懂,但多一种思路就是对自己思维的扩展。
可能有人会说,上面那个输入看起来还是很麻烦,能不能输入“ABCDE##”,下一层的#就不输入了(可以画图查看“下一层”都有什么)?答案是可以的

上代码

注:与上面代码相比,改动很少。关键之处在于多加了一个变量layer,说明要创建的树的深度(即有几层)
具体有哪些改动,可以和上面对比来看,由于代码块中不能标记,所以无法突出显示变动部分

void create(BTree &root,char *ch,circl cl,int layer)
{
 BTNode *q;
 if(*ch=='#')
  root=NULL;
 else
 {
  root=(BTree)malloc(sizeof(BTNode));//事先给根结点分配空间(这点经常忘记)
  (*root).data=*ch;
  cl.data[++cl.rear]=root; //根结点入队列
  int n=1;//上面已添加了根结点,所以从1开始
  while(cl.front!=cl.rear)
  {
   q=cl.data[++cl.front];//对头元素出队
   ++ch;//-----------------------------------------分析当前结点的左孩子
   (*q).lchild=(BTree)malloc(sizeof(BTNode));//使用前一定不要忘了给其分配空间
   if(*ch=='#' || n==layer)
    (*q).lchild=NULL;
   else
   {
    (*(*q).lchild).data=*ch;
    cl.data[++cl.rear]=(*q).lchild;
   }
   ++ch;//-----------------------------------------分析当前结点的右孩子
   (*q).rchild=(BTree)malloc(sizeof(BTNode));//使用前一定不要忘了给其分配空间
   if(*ch=='#' || n==layer)
    (*q).rchild=NULL;
   else
   {
    (*(*q).rchild).data=*ch;
    cl.data[++cl.rear]=(*q).rchild;
   }
   if(n!=layer)//这个if条件很关键 ,可以在演草纸上画下不加if时会怎样
    ++n;
  }
 }
}

运行结果

在这里插入图片描述
** ------------------------------------------------------------------------------------------------------**
上面是关键代码,下面展示些其中用到的一些代码:

  1. 队列结构体类型定义
typedef struct circl
{
 BTNode *data[maxsize];
 int front;//队头指针
 int rear;//队尾指针
}circl;
  1. 在使用队列前,不要忘了将其初始化:
void init(circl &cl)//注意为引用型
{
 cl.front=cl.rear=0;
}

或者在每次使用前写上“cl.front=cl.rear=0”也可,而无需再定义上面函数

  1. 上述函数void create(BTree &root,char *ch,circl cl)中,用到了字符型指针ch,其实这个用于接收传过来的数组名,而这个数组里存放的就是我们输入的各结点元素值,在主函数中的相关代码如下:
 char ch[maxsize];//maxsize是预定义常量
 gets(ch);

Over!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值