【数据结构与算法】two X 树的遍历以及功能实现(上)

简介: 【数据结构与算法】two X 树的遍历以及功能实现(上)

前言:

       前面我们已经提到过树、二叉树的概念及结构、堆排序、Top-k问题等的知识点,这篇文章我们来详解一下二叉树的链式结构等问题。

💥🎈个人主页:Dream_Chaser~ 🎈💥

✨✨专栏:http://t.csdn.cn/oXkBa

⛳⛳本篇内容:c语言数据结构--二叉树的遍历以及功能实现

869b18be53c8456bad658703cc0743cb.gif


一.链式二叉树存储的概念


       二叉树的链式存储结构是指: 用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。

       通常的方法是链表中每个结点由三个域组成, 数据域和左右指针域,左右指针分别用来给出该结点 左孩子和右孩子所在的链结点的存储地址

链式结构又分为二叉链和三叉链,当前我们学习中一般都是二叉链,后面课程学到高阶数据结构如红黑树等会用到三叉链。

084abc567528432199110fb0a56634d1.png


二.链式二叉树结构的实现


2.1 前置说明

       在学习二叉树的基本操作前,需先要创建一棵二叉树,然后才能学习其相关的基本操作。

 由于现在大家对二叉树结构掌握还不够深入,为了降低大家学习成本,

       此处手动快速创建一棵简单的二叉树,快速进入二叉树操作学习,等二叉树结构了解的差不多时,我们反过头再来研究二叉树真正的创建方式。

typedef int BTDataType;
typedef struct BinaryTreeNode
{
  BTDataType data;
  struct BinaryTreeNode* left;
  struct BinaryTreeNode* right;
}BTNode;
BTNode* BuyNode(BTDataType x)
{
  BTNode* node = (BTNode*)malloc(sizeof(BTNode));
  if (node == NULL)
  {
    perror("malloc fail");
    return NULL;
  }
  node->data = x;
  node->left = NULL;
  node->right = NULL;
  return node;
}
BTNode* CreatBinaryTree()
{
  BTNode* node1 = BuyNode(1);
  BTNode* node2 = BuyNode(2);
  BTNode* node3 = BuyNode(3);
  BTNode* node4 = BuyNode(4);
  BTNode* node5 = BuyNode(5);
  BTNode* node6 = BuyNode(6);
  node1->left = node2;
  node1->right = node4;
  node2->left = node3;
  node4->left = node5;
  node4->right = node6;
  return node1;
}

注意:上述代码并不是创建二叉树的方式,真正创建二叉树方式后序详解重点讲解。

再看二叉树基本操作前,再回顾下二叉树的概念, 二叉树是:

1. 空树

2. 非空:根节点,根节点的左子树、根节点的右子树组成的。

6b8f3a307d754466b18ff162814538ba.png

     从概念中可以看出,二叉树定义是递归式的,因此后序基本操作中基本都是按照该概念实现的。


2.2二叉树的遍历

    学习二叉树结构,最简单的方式就是遍历。所谓 二叉树遍历(Traversal)是按照某种特定的规则,依次对二叉树中的节点进行相应的操作, 并且每个节点只操作一次。访问结点所做的操作依赖于具体的应用问题。 遍历是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。

98b83288d70e465aa9e89b1d5809647e.png

以先序遍历为例子:

c9b9eb4310b043ba91bb4ef2b628eb36.png


前序遍历(Preorder Traversal)

       亦称先序遍历,访问根结点的操作发生在遍历其左右子树之前.

525d042a2b5946779591d7a192f7c5ac.png

中序遍历(Inorder Traversal)

访问根结点的操作发生在遍历其左右子树之中(间)

fe55a37a15254785bd98cdce26eb3e2f.png


后续遍历(Postorder Traversal)

访问根结点的操作发生在遍历其左右子树之后.

bfa9692bb0234dc5a6df118f42fef2c3.png

 由于被访问的结点必是某子树的根, 所以N(Node)、L(Left subtree)和R(Right subtree)又可解释为根、根的左子树和根的右子树。NLR、LNR和LRN分别又称为先根遍历、中根遍历和后根遍历


层序遍历(LevelOrder)

层序遍历 : 除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历。设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。

1c29a1fe85f94565b64ffcd98407429a.png


2.3二叉树功能的实现

二叉树结构定义(struct BinaryTreeNode)

代码实现:

typedef int BTDataType;
typedef struct BinaryTreeNode
{
  BTDataType data;
  struct BinaryTreeNode* left;
  struct BinaryTreeNode* right;
}BTNode;


二叉树节点的创建(CreatBinaryTree)
BTNode* BuyNode(BTDataType x)//树中一个节点的创建
{
  BTNode* node = (BTNode*)malloc(sizeof(BTNode));
  if (node == NULL)
  {
    perror("malloc fail");
    return NULL;
  }
  node->data = x;
  node->left = NULL;
  node->right = NULL;
  return node;
}
BTNode* CreatBinaryTree()//树的构造
{
  BTNode* node1 = BuyNode(1);
  BTNode* node2 = BuyNode(2);
  BTNode* node3 = BuyNode(3);
  BTNode* node4 = BuyNode(4);
  BTNode* node5 = BuyNode(5);
  BTNode* node6 = BuyNode(6);
  node1->left = node2;
  node1->right = node4;
  node2->left = node3;
  node4->left = node5;
  node4->right = node6;
  return node1;
}


二叉树的前序遍历函数(PrevOrder)

       递归不可能一直调用函数,因为这个过程一直在创建栈帧,即使栈再大,也会栈溢出。所以肯定会回归,回归的本质就是销毁栈帧。

递归是由两个部分构成:

1.子问题

2.返回条件

图解:

40778ff82a654e4886a9484ee201512b.png

7d6e38550fc74fcd994c07474791e772.png

代码实现:

void PrevOrder(BTNode* root)
{
  if (root == NULL)
  {
    printf("N ");
    return;
  }
  printf("%d ", root->data);
  PrevOrder(root->left);
  PrevOrder(root->right);
}


二叉树的中序遍历函数(InOrder)

绘图:

b35c54a1ec7d4d4f8d539abc3e8373fe.png

void InOrder(BTNode* root) 
{
  if (root == NULL)
  {
    printf("N ");
    return;
  }
  InOrder(root->left);
  printf("%d ", root->data);
  InOrder(root->right);
}
二叉树的后序遍历函数(PostOrder)

       跟前中序的思路相差不大,这里就不绘图了。

代码实现:

void PostOrder(BTNode* root)
{
  if (root == NULL)
  {
    printf("N ");
    return;
  }
  PostOrder(root->left);
  PostOrder(root->right);
  printf("%d ", root->data);
}


统计二叉树节点个数(BTreeSize)

画出递归展开图:

b0ed7f46891b41118dcf5066239038c2.png

int BTreeSize(BTNode* root)
{
  //写法一
  if (root == NULL)
    return 0;
  return BTreeSize(root->left) + BTreeSize(root->right) + 1;
  //写法二
  return root == NULL ? 0 : BTreeSize(root->left) + BTreeSize(root->right) + 1;
}
求出叶子节点的数量(BTreeLeafSize)

a8627ab6306941aa9b28a83aed725343.png

     进入函数首先判断根节点是否为空,为空就直接返回0,说明树为空,直接返回叶子节点数量为0。


       接下来,检查当前的节点是叶子节点还是分支节点,若代码检查当前节点是否为叶子节点,即该节点的左子节点和右子节点都为空。如果是叶子节点,返回叶子节点数量为1。


       如果当前节点为分支节点,则继续调用该函数,计算左子树和右子树的叶子节点数量,并将它们相加,得到当前节点为根的子树的叶子节点数量。

最后,函数返回左子树和右子树叶子节点数量的和,即整个二叉树的叶子节点数量。

int BTreeLeafSize(BTNode* root)//接受一个指向二叉树节点的指针root作为参数
{
  if (root == NULL)//代码检查根节点是否为空
  {
    return 0;
  }
  if ( root->left==NULL &&root->right==NULL)
  {
    return 1;
  }
  return BTreeLeafSize(root->left) + BTreeLeafSize(root->right);
}


相关文章
|
21天前
|
算法
数据结构之博弈树搜索(深度优先搜索)
本文介绍了使用深度优先搜索(DFS)算法在二叉树中执行遍历及构建链表的过程。首先定义了二叉树节点`TreeNode`和链表节点`ListNode`的结构体。通过递归函数`dfs`实现了二叉树的深度优先遍历,按预序(根、左、右)输出节点值。接着,通过`buildLinkedList`函数根据DFS遍历的顺序构建了一个单链表,展示了如何将树结构转换为线性结构。最后,讨论了此算法的优点,如实现简单和内存效率高,同时也指出了潜在的内存管理问题,并分析了算法的时间复杂度。
39 0
|
13天前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
32 5
|
1月前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
68 16
|
27天前
|
算法
分享一些提高二叉树遍历算法效率的代码示例
这只是简单的示例代码,实际应用中可能还需要根据具体需求进行更多的优化和处理。你可以根据自己的需求对代码进行修改和扩展。
|
1月前
|
存储 缓存 算法
如何提高二叉树遍历算法的效率?
选择合适的遍历算法,如按层次遍历树时使用广度优先搜索(BFS),中序遍历二叉搜索树以获得有序序列。优化数据结构,如使用线索二叉树减少空指针判断,自定义节点类增加辅助信息。利用递归与非递归的特点,避免栈溢出问题。多线程并行遍历提高速度,注意线程安全。缓存中间结果,避免重复计算。预先计算并存储信息,提高遍历效率。综合运用这些方法,提高二叉树遍历算法的效率。
50 5
|
1月前
|
算法
树的遍历算法有哪些?
不同的遍历算法适用于不同的应用场景。深度优先搜索常用于搜索、路径查找等问题;广度优先搜索则在图的最短路径、层次相关的问题中较为常用;而二叉搜索树的遍历在数据排序、查找等方面有重要应用。
27 2
|
1月前
|
机器学习/深度学习 JSON 算法
二叉树遍历算法的应用场景有哪些?
【10月更文挑战第29天】二叉树遍历算法作为一种基础而重要的算法,在许多领域都有着不可或缺的应用,它为解决各种复杂的问题提供了有效的手段和思路。随着计算机科学的不断发展,二叉树遍历算法也在不断地被优化和扩展,以适应新的应用场景和需求。
32 0
|
21天前
|
算法
数据结构之文件系统模拟(树数据结构)
本文介绍了文件系统模拟及其核心概念,包括树状数据结构、节点结构、文件系统类和相关操作。通过构建虚拟环境,模拟文件的创建、删除、移动、搜索等操作,展示了文件系统的基本功能和性能。代码示例演示了这些操作的具体实现,包括文件和目录的创建、移动和删除。文章还讨论了该算法的优势和局限性,如灵活性高但节点移除效率低等问题。
40 0
|
2月前
|
Java C++
【数据结构】探索红黑树的奥秘:自平衡原理图解及与二叉查找树的比较
本文深入解析红黑树的自平衡原理,介绍其五大原则,并通过图解和代码示例展示其内部机制。同时,对比红黑树与二叉查找树的性能差异,帮助读者更好地理解这两种数据结构的特点和应用场景。
34 0
|
7天前
|
算法
基于WOA算法的SVDD参数寻优matlab仿真
该程序利用鲸鱼优化算法(WOA)对支持向量数据描述(SVDD)模型的参数进行优化,以提高数据分类的准确性。通过MATLAB2022A实现,展示了不同信噪比(SNR)下模型的分类误差。WOA通过模拟鲸鱼捕食行为,动态调整SVDD参数,如惩罚因子C和核函数参数γ,以寻找最优参数组合,增强模型的鲁棒性和泛化能力。