数据结构 | 二叉树的概念及前中后序遍历(二)

简介: 数据结构 | 二叉树的概念及前中后序遍历(二)

数据结构 | 二叉树的概念及前中后序遍历(一):https://developer.aliyun.com/article/1426944

五、二叉树的性质

  1. 每个节点最多有两个子节点: 每个节点最多有两个子节点,左子节点和右子节点。
  2. 每个节点有零个、一个或两个子节点: 这意味着一个节点可以是叶节点(没有子节点)、有一个子节点,或者有两个子节点。
  3. 左子树和右子树是有序的: 对于二叉搜索树(BST),左子树中的每个节点的值都小于该节点的值,右子树中的每个节点的值都大于该节点的值。
  4. 树的高度: 树的高度是从根节点到最深叶节点的最长路径。一棵有n个节点的二叉树的高度最多为n,最少为log₂(n+1)。
  5. 最后一层节点集中在左侧: 在完全二叉树中,最后一层的节点从左到右排列,缺失的位置只会出现在最右边。
  6. 满二叉树: 一棵高度为h且有2^h - 1个节点的二叉树被称为满二叉树。
  7. 最后一层节点集中在左侧: 在完全二叉树中,最后一层的节点从左到右排列,缺失的位置只会出现在最右边。
  8. 满二叉树: 一棵高度为h且有2^h - 1个节点的二叉树被称为满二叉树。

六、二叉树的存储结构

6.1 顺序存储结构

  • 在顺序存储结构中,使用数组来表示二叉树。具体的方式是按照从上到下、从左到右的顺序将二叉树的节点依次存储在数组中。如果一个节点的编号为i,则其左子节点的编号为2i,右子节点的编号为2i+1。

例如:

1
       / \
      2   3
     / \ / \
    4  5 6  7
  • 对应的顺序存储结构为:
[1, 2, 3, 4, 5, 6, 7]
  • 这里数组的索引从1开始,根节点对应索引1,而左子节点和右子节点的关系则按照 2i 和 2i+1 的规则排列。

6.2 链式存储结构

  • 在链式存储结构中,每个节点通过指针或引用指向其左子节点和右子节点。这样的存储结构更加直观,也更容易实现。节点的定义如下:
struct TreeNode {
    int data; // 节点的数据
    TreeNode* left; // 指向左子节点的指针
    TreeNode* right; // 指向右子节点的指针
};
      1
       / \
      2   3
     / \ / \
    4  5 6  7

每个节点的 leftright 指针分别指向其左子节点和右子节点。这种存储结构更直观,但相对于顺序存储结构,可能会占用更多的内存空间。

typedef int BTDataType;
// 二叉链
struct BinaryTreeNode
{
  struct BinTreeNode* _pLeft; // 指向当前节点左孩子
  struct BinTreeNode* _pRight; // 指向当前节点右孩子
  BTDataType _data; // 当前节点值域
}
// 三叉链
struct BinaryTreeNode
{
  struct BinTreeNode* _pParent; // 指向当前节点的双亲
  struct BinTreeNode* _pLeft; // 指向当前节点左孩子
  struct BinTreeNode* _pRight; // 指向当前节点右孩子
  BTDataType _data; // 当前节点值域
};

6.3 二叉树的顺序结构及实现

  • 普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统虚拟进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段。

七、二叉树链式结构的实现

  • 在学习二叉树的基本操作前,需先要创建一棵二叉树,然后才能学习其相关的基本操作。由于现在大家对二叉树结构掌握还不够深入,为了降低大家学习成本,此处手动快速创建一棵简单的二叉树,快速进入二叉树操作学习,等二叉树结构了解的差不多时,我们反过头再来研究二叉树真正的创建方式。
  • 我们先回顾一下二叉树的概念:
  1. 空树
  2. 非空:根节点,根节点的左子树、根节点的右子树组成的。

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

八、二叉树的遍历【重点】

8.1 前序、中序以及后序遍历

  1. 前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点的操作发生在遍历其左右子树之前。简单来说就是访问顺序就是根 左子树 右子树
  2. 中序遍历(Inorder Traversal)——访问根结点的操作发生在遍历其左右子树之中(间)。简单来说就是访问顺序就是 左子树 根 右子树
  3. 后序遍历(Postorder Traversal)——访问根结点的操作发生在遍历其左右子树之后。简单来说就是访问顺序就是 左子树 右子树 根

构建一棵树

BTNode* BuyTreeNode(int x)
{
  BTNode*node = (BTNode*)malloc(sizeof(BTNode));
  assert(node);
  node->data = x;
  node->left = NULL;
  node->right = NULL;
  return node;
}
BTNode* CreateTree()
{
  BTNode* node1 = BuyTreeNode(1);
  BTNode* node2 = BuyTreeNode(2);
  BTNode* node3 = BuyTreeNode(3);
  BTNode* node4 = BuyTreeNode(4);
  BTNode* node5 = BuyTreeNode(5);
  BTNode* node6 = BuyTreeNode(6);
  node1->left = node2;
  node1->right = node4;
  node2->left = node3;
  node4->left = node5;
  node4->right = node6;
  return node1;
}

二叉树的前序遍历

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

二叉树中序遍历

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

二叉树后序遍历

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

测试

int main()
{
  BTNode* root = CreateTree();
  printf("二叉树前序遍历:\n");
  BinaryTreePrevOrder(root);
  printf("\n");
  printf("二叉树中序遍历:\n");
  BinaryTreeInOrder(root);
  printf("\n");
  printf("二叉树后序遍历:\n");
  BinaryTreePostOrder(root);
  printf("\n");
  return 0;
}
{

c6e59771153f1b9e5fa028fc6132c437_516bdb2b34134cbeb4977c7013f0314c.png

相关文章
|
30天前
|
存储 算法
数据结构与算法学习二二:图的学习、图的概念、图的深度和广度优先遍历
这篇文章详细介绍了图的概念、表示方式以及深度优先遍历和广度优先遍历的算法实现。
45 1
数据结构与算法学习二二:图的学习、图的概念、图的深度和广度优先遍历
|
7天前
|
C语言
【数据结构】二叉树(c语言)(附源码)
本文介绍了如何使用链式结构实现二叉树的基本功能,包括前序、中序、后序和层序遍历,统计节点个数和树的高度,查找节点,判断是否为完全二叉树,以及销毁二叉树。通过手动创建一棵二叉树,详细讲解了每个功能的实现方法和代码示例,帮助读者深入理解递归和数据结构的应用。
38 8
|
30天前
|
存储 算法 关系型数据库
数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
这篇文章主要介绍了多路查找树的基本概念,包括二叉树的局限性、多叉树的优化、B树及其变体(如2-3树、B+树、B*树)的特点和应用,旨在帮助读者理解这些数据结构在文件系统和数据库系统中的重要性和效率。
18 0
数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
|
30天前
|
存储 算法 搜索推荐
数据结构与算法学习十七:顺序储存二叉树、线索化二叉树
这篇文章主要介绍了顺序存储二叉树和线索化二叉树的概念、特点、实现方式以及应用场景。
17 0
数据结构与算法学习十七:顺序储存二叉树、线索化二叉树
|
1月前
|
Java
【用Java学习数据结构系列】震惊,二叉树原来是要这么学习的(二)
【用Java学习数据结构系列】震惊,二叉树原来是要这么学习的(二)
26 1
|
29天前
|
存储 算法
探索数据结构:分支的世界之二叉树与堆
探索数据结构:分支的世界之二叉树与堆
|
30天前
|
存储 算法
数据结构与算法学习十六:树的知识、二叉树、二叉树的遍历(前序、中序、后序、层次)、二叉树的查找(前序、中序、后序、层次)、二叉树的删除
这篇文章主要介绍了树和二叉树的基础知识,包括树的存储方式、二叉树的定义、遍历方法(前序、中序、后序、层次遍历),以及二叉树的查找和删除操作。
22 0
|
8天前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
74 9
|
1天前
|
存储 算法 Java
数据结构的栈
栈作为一种简单而高效的数据结构,在计算机科学和软件开发中有着广泛的应用。通过合理地使用栈,可以有效地解决许多与数据存储和操作相关的问题。
|
4天前
|
存储 JavaScript 前端开发
执行上下文和执行栈
执行上下文是JavaScript运行代码时的环境,每个执行上下文都有自己的变量对象、作用域链和this值。执行栈用于管理函数调用,每当调用一个函数,就会在栈中添加一个新的执行上下文。