针对考研的C语言学习(二叉树专题)

二叉树层次建树

对于二叉树,建树过程中需要一个(尾插法的)链表(或队列)来辅助确认当前父亲节点

由于尾插法需要一个尾指针。因此可以理解为队列,只不过是不带头结点的链表版队列。

但其实就是一个辅助找到当前父亲节点的作用,不必纠结是啥名字。

代码如下:

#include<stdio.h>
#include<stdlib.h>
typedef char ElemType;
//树结构体
typedef struct tree_node{
  ElemType val;
  struct tree_node*lc;
  struct tree_node*rc;
}Tnode,*BTree;

//链表
typedef struct link{
  BTree tree;//存储的是树的节点
  struct link*next;
}LinkNode,*LinkList;

void build_tree(BTree&tree,LinkList&front,LinkList& rear)
{
    //还需要一个指向当前父亲节点的指针
    LinkList cur = NULL;
    ElemType data;
    while(scanf("%c",&data) && data != '\n')
    {
        //每次来一个新建一个树的节点和链表的节点
        BTree newTree = (BTree)calloc(1,sizeof(Tnode));
        LinkList newList = (LinkList)calloc(1,sizeof(LinkNode));
        newTree->val = data;
        newList->tree=newTree;
        //进行判读是不是父亲节点
        if(tree == NULL)
        {
            tree = newTree;
            //入队
            front = rear = newList;
            cur=rear;
        }
        else
        {
            if(cur->tree->lc == NULL)
            {
                //插入左子树
                cur->tree->lc=newTree;
                //入队并更新尾指针
                rear->next=newList;
                rear = rear->next;
            }
            else
            {
                cur->tree->rc = newTree;
                //入队并更新尾指针
                rear->next=newList;
                rear = rear->next;
                //注意这里左右子树都满了,当前父亲节点要换
                cur= cur->next;
            }
        }
    }
}

//前序便利
void pre_print(BTree tree)
{
    if(tree)
    {
        putchar(tree->val);
        pre_print(tree->lc);
        pre_print(tree->rc);
    }
}
void mid_print(BTree tree)
{
    if(tree)
    {
        //左跟右
        mid_print(tree->lc);
        putchar(tree->val);
        mid_print(tree->rc);
    }
}
void post_print(BTree tree)
{
    if(tree)
    {
        //左右跟
        post_print(tree->lc);
        post_print(tree->rc);
        putchar(tree->val);
    }
}
int main()
{
    BTree tree = NULL;//树根
    LinkList front=NULL;
    LinkList rear=NULL;//需要用到尾插法
    build_tree(tree,front,rear);
    pre_print(tree);
    puts("");
    mid_print(tree);
    puts("");
    post_print(tree);
	return 0;
}

前序便利:根左右--->先打印自身再左子树再右子树

//前序便利
void pre_print(BTree tree)
{
    if(tree)
    {
        putchar(tree->val);
        pre_print(tree->lc);
        pre_print(tree->rc);
    }
}

中序遍历:左根右--->先打印左子树再打印自身再右子树

void mid_print(BTree tree)
{
    if(tree)
    {
        //左跟右
        mid_print(tree->lc);
        putchar(tree->val);
        mid_print(tree->rc);
    }
}

后序遍历:左右根--->先打印左子树再右子树再自身

void post_print(BTree tree)
{
    if(tree)
    {
        //左右跟
        post_print(tree->lc);
        post_print(tree->rc);
        putchar(tree->val);
    }
}

【注意】以上三中便利采用递归思想。

代码运行结果如下

封装思想展示,队列封装

#include<stdio.h>
#include<stdlib.h>
typedef char ElemType;

//树
typedef struct trees{
    ElemType data;
    struct trees*lc;
    struct trees*rc;
}treeNode,*Tree;

//链表
typedef struct Links{
    Tree tree;
    struct Links*next;
}LNode,*LinkList;

//队列
typedef struct{
  LinkList front;
  LinkList rear;
}LinkQue;

void init_que(LinkQue&q)
{
    q.front=q.rear=(LinkList)calloc(1,sizeof(LNode));
    q.front=q.rear;
}

bool isEmpty(LinkQue&q)
{
    return q.front == q.rear;
}

//入队
void push_que(LinkQue&q,Tree tree)
{
    //新建链表节点
    LinkList newList = (LinkList)calloc(1,sizeof(LNode));
    newList->next=NULL;
    newList->tree=tree;
    q.rear->next=newList;
    q.rear=q.rear->next;
}
bool pop_que(LinkQue&q,Tree &tree)
{
    if(isEmpty(q))
    {
        return false;
    }
    LinkList del = q.front->next;//头结点不存数据,第一个节点才是真的数据起始位置
    q.front->next=del->next;//断链
    tree=del->tree;
    if(q.rear == del)//只剩下尾节点的数据
    {
        q.rear=q.front;//置空
    }
    free(del);
    return true;
}

void build_tree(Tree&tree)
{
    LinkQue q;
    init_que(q);
    LinkList cur = NULL;
    ElemType data;
    while(scanf("%c",&data) && data != '\n')
    {
        Tree newTree = (Tree)calloc(1,sizeof(treeNode));//申请新的树的节点
        newTree->data=data;
        if(tree == NULL)
        {
            tree = newTree;
            push_que(q,tree);//入队
            cur = q.rear;
        }
        else
        {
            if(cur->tree->lc == NULL)
            {
                cur->tree->lc = newTree;
                push_que(q,newTree);
            }
            else
            {
                cur->tree->rc = newTree;
                push_que(q,newTree);
                //改变当前父亲节点
                cur = cur->next;
            }
        }
    }
}

void pre_print(Tree t)
{
    if(t)
    {
        putchar(t->data);
        pre_print(t->lc);
        pre_print(t->rc);
    }
}
void mid_print(Tree t)
{
    if(t)
    {
        mid_print(t->lc);
        putchar(t->data);
        mid_print(t->rc);
    }
}
void post_print(Tree t)
{
    if(t)
    {
        post_print(t->lc);
        post_print(t->rc);
        putchar(t->data);
    }
}


int main()
{
    Tree tree = NULL;
    build_tree(tree);
    // pre_print(tree);
  
    return 0;
}

层次遍历在下节

相关推荐
HABuo13 分钟前
【数据结构与算法】合并链表、链表分割、链表回文结构
c语言·开发语言·数据结构·c++·学习·算法·链表
带多刺的玫瑰25 分钟前
Leecode刷题C语言之网络延迟时间
c语言·开发语言·算法
AI完全体34 分钟前
【AI日记】24.11.25 学习谷歌数据分析初级课程-第6课
学习·数据分析
奇妙之二进制1 小时前
2025年春招修订版《C/C++笔面试系列》(1) C语言经典笔面试题(上)
c语言·c++·面试
L73S371 小时前
HTML详解(1)
程序人生·考研·学习方法
码到成龚1 小时前
《数字图像处理基础》学习06-图像几何变换之最邻近插值法缩小图像
图像处理·学习
fa_lsyk1 小时前
mysql window安装(学习使用)
学习·mysql·adb
熬夜的猪2 小时前
现代安全密码哈希算法
java·学习·算法·安全·哈希算法
kuiini2 小时前
C 语言学习-06【指针】
c语言·学习
დ旧言~2 小时前
实战项目 Boost 搜索引擎
服务器·c语言·前端·网络·汇编·c++