【C语言数据结构(基础版)】第五站:树和二叉树(下)

简介: 【C语言数据结构(基础版)】第五站:树和二叉树

这就是我们的大致思路,而要实现这个首先,我们得导入我们队列,导入之后,我们需要修改的部分就是这两个,前置声明,因为我们的树是在他的里面定义的,所以在队列的头文件里面是不认识树结点的,所以我们得先声明一下,定义就在后面让他去找去。

 所以他最终的代码为

//层序遍历
void LevelOrder(BTNode* root)
{
  Queue q;
  QueueInit(&q);
  if (root != NULL)
  {
    QueuePush(&q, root);
  }
  while (!QueueEmpty(&q))
  {
    BTNode* front = QueueFront(&q);
    QueuePop(&q);
    printf("%c ", front->date);
    if (root->left != NULL)
    {
      QueuePush(&q, front->left);
    }
    if (root->right != NULL)
    {
      QueuePush(&q, front->right);
    }
  }
  printf("\n");
  QueueDestory(&q);
}

运行结果为

5.二叉树的销毁

想要销毁这颗二叉树,那么我们就必须得使用后序的方式来进行销毁,如果根节点是NULL,那么什么也不用做,如果不是空,那么就先销毁他的左子树,然后销毁右子树,最后销毁该结点。如此递归下去即可,代码如下

void DestoryTree(BTNode* root)
{
  if (root == NULL)
  {
    return;
  }
  DestoryTree(root->left);
  DestoryTree(root->right);
  free(root);
  root = NULL;
}

6.二叉树的一些选择题

1.某完全二叉树按层次输出(同一层从左到右)的序列为 ABCDEFGH 。该完全二叉树的前序序列为( )

A、 ABDHECFG         B、 ABCDEFGH         C、 HDBEAFCG         D、 HDEBFGCA

对于这道题,最关键的部分是完全二叉树这几个字眼。由此我们直接得出该完全二叉树的图

而他的先序遍历我们很容易就得知,A B D H E C F G

所以选A

2.二叉树的先序遍历和中序遍历如下:先序遍历:EFHIGJK;中序遍历:HFIEJKG.则二叉树根结点为 ()

A、E         B、 F         C、 G         D、 H

对于这道题其实不用中序遍历我们也能做出来,因为我们知道先序遍历第一个肯定是根节点,所以就直接得出答案为E

但是呢我们也要知道先序遍历和中序遍历其实是可以确定一个二叉树的。我们现在画出他的二叉树,首先先序遍历我们可以确定根,所以我们知道首先有一个根E,有了根以后,我们根据这个根在中序遍历中的位置就能确定出左右区间,所以HFI部分为左子树,JKG部分为右子树。而HFI这一部分我们又回到先序遍历中,我们可以看出F是根,我们由这个F是根又回到中序遍历中确定他的左右子树区间,我们不难得出,H就是F的左子树,I就是F的右子树。同理,我们可以得出JKG部分的结构,G为根节点,J和K都是左子树部分,而JK部分中,J又是根节点,而K 是J 的右子树

最终我们得出这颗二叉树为

3.设一课二叉树的中序遍历序列:badce,后序遍历序列:bdeca,则二叉树前序遍历序列为____。

A、 adbce         B、 decab         C、 debac         D、 abcde

这道题和上一道题是一样的,我们可以根据中序遍历和后序写出他的二叉树。这里直接给出他的二叉树

所以他的先序遍历为abcde

7.牛客题目之二叉树遍历

在这里也给出一道题

题目链接:二叉树遍历_牛客题霸_牛客网

题目描述:

(1)思路分析

首先我们先将思路给理清楚,二叉树的中序遍历并不难,难的是如何根据输入的字符串去构建二叉树。他的构建过程是这样的,因为他是根据先序遍历来构建的,那么第一个a肯定就是根结点,然后第二个b就是左子树的根节点,如此下来,c也是b的左子树的根结点,这时候我们该看c的左子树了,但是下一个数据是#,也就是说c的左子树是一个空,那么就该插入c的右子树了,而这个右子树恰好也是一个空。所以就返回到b的右子树了,b的右子树是一个d,d的左子树是一个e,e的左子树又是空,e的右子树是g,g的左右子树都是空。所以现在回到了d的右子树了,d的右子树刚好是一个f,而f的左右子树都是空,所以现在回到了a,a的右子树是一个空。

这样一来二叉树就构建完成了,如下图所示

有了二叉树构建完成,那么这道题简直就是易如反掌了

(2)解题代码

#include <stdio.h>
#include <stdlib.h>
typedef struct TreeNode
{
    struct TreeNode* left;
    struct TreeNode* right;
    char val;
}TreeNode;
TreeNode* CreateTree(char* str,int* i)
{
    if(str[*i]=='#')
    {
        (*i)++;
        return NULL;
    }
    TreeNode* root=(TreeNode*)malloc(sizeof(TreeNode));
    if(root==NULL)
    {
        printf("malloc fail\n");
        exit(-1);
    }
    root->val=str[*i];
    (*i)++;
    root->left=CreateTree(str,i);
    root->right=CreateTree(str,i);
    return root;
}
void InOrder(TreeNode* root)
{
    if(root==NULL)
    {
        return ;
    }
    InOrder(root->left);
    printf("%c ",root->val);
    InOrder(root->right);
}
int main() 
{
    char str[101]={0};
    scanf("%s",str);
    int i=0;
    TreeNode* root = CreateTree(str,&i);
    InOrder(root);
    return 0;
}

四、哈夫曼树的建立以及编码

在这里也简单提及一下哈夫曼树,实际上哈夫曼树应用并不多。一般只应用于文件压缩。在这里简单的提及一下哈夫曼树的建立以及他的编码

假设我们有如下四个结点,a、b、c、d相当于他们的编号,7、5、2、4则是他们的权值,我们利用这四个结点来构造一颗哈夫曼树

我们的构造过程是这样的,先找出最小的和次最小的两个结点,然后让最小的放在左边,次最小的放在右边,然后再他们这两个结点上面构造一个双亲结点。这个双亲结点的权值是他们两个的权值之和

然后接下来将这个6这个结点和剩余的结点放在一块,找出他们的最小的两个结点,同样最小的放在左边,次最小的放在右边

跟上面同样的道理,继续将剩余的找出最小的两个

这样一来,我们就构建出哈夫曼树了,上面的就是哈夫曼树

有了哈夫曼树,我们还会对其进行编码,我们将每一个左子树编码为0,右子树编码为1

有了这些编码,我们就可以知道每一个结点的编码是多少了

比如a的编码为0、b的编码为10、c的编码为110、d的编码为111

而这些编码就是哈夫曼编码

这棵树也叫做加权路径最优二叉树,也就是所有原结点的权值*路径长度和最小

即:权值越大、路径越短、编码越短;权值越小、路径越长、编码越长。


总结

本小节讲解了树的概念,二叉树的性质,二叉树的先序中序后序层序遍历以及计算叶子结点,总结点个数的实现,最后还有哈夫曼树的建立以及编码

如果对你有帮助,不要忘记点赞加收藏哦!!!

想获得更多优质的内容, 一定不要忘记关注我哦!!!

相关文章
|
4月前
|
算法 数据处理 C语言
C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合
本文深入解析了C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合,旨在帮助读者掌握这一高效的数据处理方法。
112 1
|
16天前
|
定位技术 C语言
c语言及数据结构实现简单贪吃蛇小游戏
c语言及数据结构实现简单贪吃蛇小游戏
|
2月前
|
存储 C++
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
【数据结构——树】哈夫曼树(头歌实践教学平台习题)【合集】目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:任务描述 本关任务:编写一个程序构建哈夫曼树和生成哈夫曼编码。 相关知识 为了完成本关任务,你需要掌握: 1.如何构建哈夫曼树, 2.如何生成哈夫曼编码。 测试说明 平台会对你编写的代码进行测试: 测试输入: 1192677541518462450242195190181174157138124123 (用户分别输入所列单词的频度) 预
68 14
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
|
2月前
|
搜索推荐 C语言
数据结构(C语言)之对归并排序的介绍与理解
归并排序是一种基于分治策略的排序算法,通过递归将数组不断分割为子数组,直到每个子数组仅剩一个元素,再逐步合并这些有序的子数组以得到最终的有序数组。递归版本中,每次分割区间为[left, mid]和[mid+1, right],确保每两个区间内数据有序后进行合并。非递归版本则通过逐步增加gap值(初始为1),先对单个元素排序,再逐步扩大到更大的区间进行合并,直至整个数组有序。归并排序的时间复杂度为O(n*logn),空间复杂度为O(n),且具有稳定性,适用于普通排序及大文件排序场景。
|
2月前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
59 12
|
2月前
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
53 10
|
2月前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
55 2
|
4月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
102 1
|
4月前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
64 1
|
2月前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
158 77