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

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

(2)先序遍历

那么这个树的分割我们直到了,它对我们的先序中序后序遍历树有什么用呢?

我们先看先序遍历,其实先序也称作先根,如下图所示,先根就很通俗易懂了,先访问根,再访问左子树,再访问右子树。

那么我们按照这个思路用先序的方式去访问一下这棵树吧,首先这棵树得先访问根节点A

然后我们开始访问左子树B,访问这颗左子树的时候,我们又先访问左子树的根,也就是B

访问完B的根了,我们就要访问它的左子树D,而它的左子树D,又要先访问它的根,也就是D

访问了D的根节点,那么我们又要访问它的左子树,而它的左子树是空

然后继续访问D的右子树,刚好它也是空

D这棵树访问完了,而D是属于B的左子树,那么我们就应该访问B的右子树E了,而它的访问也一样,先访问根节点,再访问左子树,在访问右子树

然后我们就发现,其实B这颗树也访问完成了,那么这下也就是A的左子树访问完了,该访问A的右子树了,而A的右子树C,它也是先访问根节点C,然后访问左右两颗树,而它的左右两颗树刚好都是空的

这就是我们的先序遍历了。当然有的书上没有NULL这个东西,这个其实也不影响的

(3)中序遍历

有了先序遍历的理解那么其实,中序遍历我们也很容易就能写出来了,因为中序遍历其实就是先左子树,根,最后右子树

那么我们简单的分析一下:

首先这颗树分为根节点A,左子树B,右子树C。那么我们因为是中序遍历,所以得先访问B这颗左子树。而B这颗左子树又分为根节点B,左子树D,右子树E。所以我们还得先访问D这颗树,而D这颗树,又分为根节点D,左子树NULL,右子树NULL。到了这里左子树已经到头了,所以我们该返回去了,所以目前的访问顺序就是NULL D NULL B,这样也就是B的左子树以及它的根已经访问完了,现在该访问B的右子树了,而这个根D是一样的过程,所以目前我们的访问顺序就成了NULL D NULL B NULL E NULL。这样也就意味着B这颗树访问完了,而B又是A这颗树上的左子树,所以现在将A一访问,就该访问右子树C了,而C的右子树又分为左子树NULL根C右子树NULL。

所以最终的访问顺序为NULL D NULL D NULL E NULL A NULL C NULL

(4)后序遍历

这个的访问我们就更加熟悉了,它的访问过程是

NULL NULL D NULL NULL E B NULL NULL C A

我们在看一个例子

这颗树的前序中序后序是

(5)先序中序后序的代码实现

根据了上面的分析,其实我们也不难得知这个是通过递归实现的,代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef char BTDateType;
typedef struct BinaryTreeNode
{
  struct BinaryTreeNode* left;
  struct BinaryTreeNode* right;
  BTDateType date;
}BTNode;
//先序
void PrevOrder(BTNode* root)
{
  if (root == NULL)
  {
    printf("NULL ");
    return;
  }
  printf("%c ", root->date);
  PrevOrder(root->left);
  PrevOrder(root->right);
}
//中序
void InOrder(BTNode* root)
{
  if (root == NULL)
  {
    printf("NULL ");
    return;
  }
  InOrder(root->left);
  printf("%c ", root->date);
  InOrder(root->right);
}
//后序
void PostOrder(BTNode* root)
{
  if (root == NULL)
  {
    printf("NULL ");
    return;
  }
  PostOrder(root->left);
  PostOrder(root->right);
  printf("%c ", root->date);
}
int main()
{
  BTNode* A = (BTNode*)malloc(sizeof(BTNode));
  A->date = 'A';
  A->left = NULL;
  A->right = NULL;
  BTNode* B = (BTNode*)malloc(sizeof(BTNode));
  B->date = 'B';
  B->left = NULL;
  B->right = NULL;  
  BTNode* C = (BTNode*)malloc(sizeof(BTNode));
  C->date = 'C';
  C->left = NULL;
  C->right = NULL;
  BTNode* D = (BTNode*)malloc(sizeof(BTNode));
  D->date = 'D';
  D->left = NULL;
  D->right = NULL;
  BTNode* E = (BTNode*)malloc(sizeof(BTNode));
  E->date = 'E';
  E->left = NULL;
  E->right = NULL;
  A->left = B;
  A->right = C;
  B->left = D;
  B->right = E;
  PrevOrder(A);
  printf("\n");
  InOrder(A);
  printf("\n");
  PostOrder(A);
  printf("\n");
}

运行结果为

2.计算二叉树中结点的个数

这个也很简单,只要我们理解了递归,那么这个就很容易了,代码如下

//计算二叉树中结点的个数
int TreeSize(BTNode* root)
{
  if (root == NULL)
  {
    return 0;
  }
  else
  {
    return 1 + TreeSize(root->left) + TreeSize(root->right);
  }
}

这是运行结果

3.计算二叉树中叶子结点的个数

这个同样很简单,如果树是空树,那么直接返回0即可,如果该结点的左孩子和右孩子都是空指针,那么返回1就可以了,说明他是一个叶子结点,其他情况我们就采用递归的思想去计算他的左孩子和右孩子的结点就可以了,代码如下

//计算叶子结点的个数
int TreeLeftSize(BTNode* root)
{
  if (root == NULL)
  {
    return 0;
  }
  else if (root->left == NULL && root->right == NULL)
  {
    return 1;
  }
  else
  {
    return TreeLeftSize(root->left) + TreeLeftSize(root->right);
  }
}

这是运行结果

4.二叉树的层序遍历(广度优先遍历)

我们先说一下广度优先遍历的基本思路,他的基本思路是这样的,需要使用一个队列

如下图所示,我们先将A入队列

然后 A出队列的同时打印他并且将他的左右孩子入队列

然后继续出B,打印他 入他的左右孩子

然后我们继续出C,入他的孩子,打印C

后面的也都是同理,出队列的同时打印他并且入他的孩子,如果没有孩子,那就不用入孩子了

相关文章
|
算法 数据处理 C语言
C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合
本文深入解析了C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合,旨在帮助读者掌握这一高效的数据处理方法。
714 1
|
算法 Java
算法系列之数据结构-Huffman树
Huffman树(哈夫曼树)又称最优二叉树,是一种带权路径长度最短的二叉树,常用于信息传输、数据压缩等方面。它的构造基于字符出现的频率,通过将频率较低的字符组合在一起,最终形成一棵树。在Huffman树中,每个叶节点代表一个字符,而每个字符的编码则是从根节点到叶节点的路径所对应的二进制序列。
391 3
 算法系列之数据结构-Huffman树
|
存储 自然语言处理 数据库
【数据结构进阶】AVL树深度剖析 + 实现(附源码)
在深入探讨了AVL树的原理和实现后,我们不难发现,这种数据结构不仅优雅地解决了传统二叉搜索树可能面临的性能退化问题,还通过其独特的平衡机制,确保了在任何情况下都能提供稳定且高效的查找、插入和删除操作。
875 19
|
存储 C++
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
【数据结构——树】哈夫曼树(头歌实践教学平台习题)【合集】目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:任务描述 本关任务:编写一个程序构建哈夫曼树和生成哈夫曼编码。 相关知识 为了完成本关任务,你需要掌握: 1.如何构建哈夫曼树, 2.如何生成哈夫曼编码。 测试说明 平台会对你编写的代码进行测试: 测试输入: 1192677541518462450242195190181174157138124123 (用户分别输入所列单词的频度) 预
538 14
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
|
定位技术 C语言
c语言及数据结构实现简单贪吃蛇小游戏
c语言及数据结构实现简单贪吃蛇小游戏
|
搜索推荐 C语言
数据结构(C语言)之对归并排序的介绍与理解
归并排序是一种基于分治策略的排序算法,通过递归将数组不断分割为子数组,直到每个子数组仅剩一个元素,再逐步合并这些有序的子数组以得到最终的有序数组。递归版本中,每次分割区间为[left, mid]和[mid+1, right],确保每两个区间内数据有序后进行合并。非递归版本则通过逐步增加gap值(初始为1),先对单个元素排序,再逐步扩大到更大的区间进行合并,直至整个数组有序。归并排序的时间复杂度为O(n*logn),空间复杂度为O(n),且具有稳定性,适用于普通排序及大文件排序场景。
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
464 12
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
249 10
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
630 3
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
579 1