【使用层次序列构建二叉树(数据结构C)】

使用层次序列构建二叉树(C语言实现)

在数据结构学习过程中,二叉树的构建方式通常有递归建树(前序/中序) 层次建树(广度优先)两种。本文将介绍一种基于辅助队列实现的层次建树方法 ,并结合前序、中序、后序遍历结果来验证构建的正确性。


🌳 示例结构

输入层次序列:a b c d e f g

预期构建出的二叉树结构如下:

复制代码
        a
      /   \
     b     c
    / \   / \
   d   e f   g

🧠 思路解析

层次建树的关键是 广度优先遍历的顺序插入节点。为了实现这一目标,我们需要:

  • 使用一个结构体指针队列,保存待填左右孩子的节点。
  • 每读入一个字符,就创建一个新树节点,并尝试插入到当前队首节点的左或右孩子位置。
  • 如果左右孩子都已填满,就将当前队首出队,指向下一个节点。

🛠️ 关键数据结构

c 复制代码
// 树节点结构体
typedef struct BiTNode {
    char data;
    struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;

// 辅助队列节点(保存 BiTree 指针)
typedef struct tag {
    BiTNode *p;
    struct tag *pnext;
} tag_t, *ptag_t;

🧩 核心建树逻辑

c 复制代码
BiTree tree = NULL; // 根节点
ptag_t phead = NULL, ptail = NULL, listpnew = NULL, pre = NULL;
char c;

while(scanf("%c", &c)) {
    if(c == '\n') break;

    BiTree pnew = (BiTree)calloc(1, sizeof(BiTNode));
    pnew->data = c;

    listpnew = (ptag_t)calloc(1, sizeof(tag_t));
    listpnew->p = pnew;

    if(tree == NULL) {
        tree = pnew;
        phead = ptail = listpnew;
        pre = listpnew;
    } else {
        ptail->pnext = listpnew;
        ptail = listpnew;

        if(pre->p->lchild == NULL) {
            pre->p->lchild = pnew;
        } else if(pre->p->rchild == NULL) {
            pre->p->rchild = pnew;
            pre = pre->pnext; // 移动到下一个节点
        }
    }
}

🔁 遍历验证

前序遍历(PreOrder):

c 复制代码
void PreOrder(BiTree p) {
    if(p != NULL) {
        printf("%c", p->data);
        PreOrder(p->lchild);
        PreOrder(p->rchild);
    }
}

中序遍历(InOrder):

c 复制代码
void InOrder(BiTree p) {
    if(p != NULL) {
        InOrder(p->lchild);
        printf("%c", p->data);
        InOrder(p->rchild);
    }
}

后序遍历(PostOrder):

c 复制代码
void PostOrder(BiTree p) {
    if(p != NULL) {
        PostOrder(p->lchild);
        PostOrder(p->rchild);
        printf("%c", p->data);
    }
}

完整代码

c 复制代码
//层次建树   借助一个辅助队列
//          a
//        b   c
//    d   e   f   g

#include <iostream>
#include<stdio.h>
#include<stdlib.h>

//借助辅助队列来进行建树
typedef struct LinkNode{
    char datac; //数据结点

}LinkNode; //建立一个结点

//这里没有使用标准的链队列来实现 相应的层次建树
typedef struct {
    LinkNode *front, *rear;
}LinkQueue;   //建立队列#

建立数的结点  使用的是链式的存储


typedef struct BiTNode{
    char data;
    struct BiTNode *lchild,*rchild;
}BiTNode , * BiTree;


//而是建立一个辅助队列 tag
typedef struct tag{
//    BiTree p;  //树的某一结点的地址值
    BiTNode *p;
    struct tag *pnext;

}tag_t , *ptag_t;

//前序遍历
void PreOrder(BiTree p){

    if(p!=NULL){

        printf("%c",p->data);
        PreOrder(p->lchild);
        PreOrder(p->rchild);
    }


}

//中序遍历
void InOrder(BiTree p){

    if(p!=NULL){

        InOrder(p->lchild);
        printf("%c",p->data);
        InOrder(p->rchild);
    }

}

//后序遍历
void PostOrder(BiTree p){

    if(p!=NULL){

        PostOrder(p->lchild);

        PostOrder(p->rchild);

        printf("%c",p->data);
    }
}



int main() {
    BiTree pnew; //用来指向新申请的数结点
    BiTree tree =NULL; //tree 是指向树根的,代表树

    ptag_t phead= NULL,ptail =NULL, listpnew =NULL, pre =NULL; //初始化队列 定义一个pre 指向执行的当前元素

     char c;

     //abcdef
     while(scanf("%c",&c)){

            if(c=='\n'){
                break;
            }
         //calloc申请空间  大小是两个参数相乘,并对空间进行初始化  赋值为0;
         //malloc 申请以后还需要对其进行赋值 malloc 返回的是 void * 类型的 也需要进行强制转换

         树申请结点
         pnew =(BiTree) calloc(1,sizeof(BiTNode));
         pnew->data = c;


         //队列结点申请空间
         listpnew = (ptag_t) calloc(1,sizeof(tag_t));  //申请一个结构体类型的结点 返回一个指针类型的

         listpnew->p =pnew;

         //如果是数的第一个结点
         if(tree==NULL){
             tree = pnew;  //tree 指向根的头结点
             //第一个结点 即是队列头也是 队列尾
             phead = ptail = listpnew;
             pre = listpnew; //  用来判断当前结点 的左右孩子是否满了

         }else {
             //元素直接入队
             ptail ->pnext = listpnew;
             ptail =listpnew;
             //接下来把元素放入树中
             if(pre->p->lchild ==NULL){
                 pre ->p ->lchild =pnew;  // pre -> p 左孩子为空 就放入左孩子

             }else if(pre->p->rchild==NULL){
                 pre->p->rchild =pnew;
                 pre = pre->pnext;  // !!! 左右孩子都满了,指向下一个节点
             }


         }

     }

    PreOrder(tree);
    printf("\n");
    InOrder(tree);
    printf("\n");
    PostOrder(tree);
     return 0;
     //这没有对树进行相应的输出  ,使用调试发现建树完成
}
//D:\TextOPT\C_CPP_code\For408\DateS\5\SqBinaryTree1\cmake-build-debug\SqBinaryTree1.exe
//123456789
//124895367
//849251637
//894526731

📌 完整输出样例

以输入:abcdefg(按层次顺序输入,以回车结束)为例:

复制代码
输入:
abcdefg↵

输出:
前序遍历:abdecfg
中序遍历:dbeafcg
后序遍历:debgfca

输出对应的树结构:

复制代码
        a
      /   \
     b     c
    / \   / \
   d   e f   g

✅ 总结

  • 使用辅助队列可以按层次方式构建二叉树,代码逻辑清晰,效率也较高。
  • 在建树过程中,记得及时更新队列指针(例如 pre = pre->pnext;)以避免插入错误。
  • 可结合三种遍历结果验证建树的正确性。

相关推荐
我想进大厂3 分钟前
图论---朴素Prim(稠密图)
数据结构·c++·算法·图论
我想进大厂8 分钟前
图论---Bellman-Ford算法
数据结构·c++·算法·图论
光而不耀@lgy13 分钟前
C++初登门槛
linux·开发语言·网络·c++·后端
lkbhua莱克瓦2418 分钟前
用C语言实现——一个中缀表达式的计算器。支持用户输入和动画演示过程。
c语言·开发语言·数据结构·链表·学习方法·交友·计算器
Mr__Miss22 分钟前
面试踩过的坑
java·开发语言
啊丢_24 分钟前
C++——Lambda表达式
开发语言·c++
Chh07151 小时前
《R语言SCI期刊论文绘图专题计划》大纲
开发语言·r语言
Yeats_Liao1 小时前
Go 语言 TCP 端口扫描器实现与 Goroutine 池原理
开发语言·tcp/ip·golang
lwewan1 小时前
26考研——存储系统(3)
c语言·笔记·考研
Thomas_YXQ2 小时前
Unity3D IK解算器技术分析
开发语言·搜索引擎·unity·全文检索·unity3d·lucene