针对考研的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;
}

层次遍历在下节

相关推荐
艾莉丝努力练剑38 分钟前
【洛谷刷题】用C语言和C++做一些入门题,练习洛谷IDE模式:分支机构(一)
c语言·开发语言·数据结构·c++·学习·算法
武昌库里写JAVA2 小时前
JAVA面试汇总(四)JVM(一)
java·vue.js·spring boot·sql·学习
Cx330❀2 小时前
【数据结构初阶】--排序(五):计数排序,排序算法复杂度对比和稳定性分析
c语言·数据结构·经验分享·笔记·算法·排序算法
杜子不疼.2 小时前
《Python学习之字典(一):基础操作与核心用法》
开发语言·python·学习
小幽余生不加糖3 小时前
电路方案分析(二十二)适用于音频应用的25-50W反激电源方案
人工智能·笔记·学习·音视频
..过云雨3 小时前
01.【数据结构-C语言】数据结构概念&算法效率(时间复杂度和空间复杂度)
c语言·数据结构·笔记·学习
myzzb3 小时前
基于uiautomation的自动化流程RPA开源开发演示
运维·python·学习·算法·自动化·rpa
岑梓铭4 小时前
考研408《计算机组成原理》复习笔记,第五章(3)——CPU的【数据通路】
笔记·考研·408·计算机组成原理·计组
谱写秋天5 小时前
在STM32F103上进行FreeRTOS移植和配置(STM32CubeIDE)
c语言·stm32·单片机·freertos
我不是板神5 小时前
程序设计|C语言教学——C语言基础2:计算与控制语句
c语言