【数据结构】二叉树(下)

简介: 【数据结构】二叉树(下)

二叉树的链式结构

  链式二叉树的增删查改是没有意义的,建立在二叉树基础上的搜索二叉树才具备增删查改的意义。但是链式二叉树是基础,就像修房子得先打地基一样。

二叉树的遍历

首先确定一个概念,二叉树分为空树和非空树,只要是非空树就有根节点、根节点的左子树和根节点的右子树。二叉树的定义是递归式的。

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

 二叉树一共有四种遍历方式,前序遍历(先根遍历)、中序遍历(中根遍历)、后序遍历(后根遍历)和层序遍历。

前序遍历(先根遍历)

  访问根节点的操作发生在遍历其左右子树之前。在遍历时,会不断向下遍历知道遇到空树才停止。

e1f4f9d7bb084fe0ad9c1831613818ea.png

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

 栈帧空间的创建销毁顺序按照下图进行的,向右的箭头表示创建,向左的箭头表示销毁。创建销毁的顺序是橙色->绿色->深蓝色->粉色->金色->紫色->青色。

fac4d8cc7ab74c8d83533721b8c265b2.png

中序遍历(中根遍历)

  访问根节点的操作放生在遍历其左右子树之间。


54d3e49e32f24fc7bd84da91c8007999.png

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

 栈帧空间的创建销毁顺序按照下图进行的,向右的箭头表示创建,向左的箭头表示销毁。创建销毁的顺序是橙色->绿色->蓝色->粉色->深蓝色->金色->青色->紫色。

21f06f17eab043c1a343477ab376358f.png

后序遍历(后根遍历)

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


0119b0dcafce4d18b03596d1ea8e3531.png

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

栈帧空间的创建销毁顺序按照下图进行的,向右的箭头表示创建,向左的箭头表示销毁。创建销毁的顺序是橙色->绿色->蓝色->粉色->深蓝色->金色->青色->紫色。

191cd7c525864c9e8679877f528d9557.png

层序遍历

  从第一层开始,每层从左到右,一层一层的走。四种遍历中,只有层序遍历是非递归的,它采用的是队列来实现的。


47942d6a2ab240d4a502825e8182c565.png

void LevelOrder(BTNode* root)
{
  Queue q;
  QueueInit(&q);
  // 先将根节点存入队列
  if (root)
    QueuePush(&q, root);
  // 判空,如果为空就不执行以下语句
  while (!QueueEmpty(&q))
  {
    // 获取队头,打印之后,移出队列
    BTNode* front = QueueFront(&q);
    printf("%d ", front->data);
    QueuePop(&q);
    if (front->left)
      QueuePush(&q, front->left);
    if (front->right)
      QueuePush(&q, front->right);
  }
  printf("\n");
  QueueDestroy(&q);
}

83f48b87f2764dd09e0640666011e996.png

二叉树的构建

  二叉树的构建根据三种递归的遍历方式进行构建,可以进行前序、中序、后序构建,我这里使用的是前序构建。

BTNode* CreatBinaryTree(BTDataType* a, int* pi)
{
  if (-1 == a[*pi])
  {
    (*pi)++;
    return NULL;
  }
  BTNode* root = (BTNode*)malloc(sizeof(BTNode));
  if (NULL == root)
  {
    perror("malloc fail");
    exit(-1);
  }
  root->data = a[(*pi)++];
  root->left = CreatBinaryTree(a, pi);
  root->right = CreatBinaryTree(a, pi);
  return root;
}

二叉树的节点数

int TreeSize(BTNode* root)
{
  if (NULL == root)
  {
    return 0;
  }
  return TreeSize(root->left) + TreeSize(root->right) + 1;
}

栈帧空间的创建销毁顺序按照下图进行的,向右的箭头表示创建,向左的箭头表示销毁。创建销毁的顺序是橙色->绿色->蓝色->粉色->深蓝色->金色->青色->紫色,最后返回的值是6。


913941f2678f4c268518b6f655bd5491.png

二叉树的叶子数

int TreeLeafSize(BTNode* root)
{
  if (NULL == root)
  {
    return 0;
  }
  if (NULL == root->left && NULL == root->right)
  {
    return 1;
  }
  return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}


栈帧空间的创建销毁顺序按照下图进行的,向右的箭头表示创建,向左的箭头表示销毁。创建销毁的顺序是橙色->绿色->蓝色->粉色->深蓝色->金色,最后结果为3。


21c8b0f8e63c4445a55c3419bde33210.png

二叉树的高度

int TreeHeight(BTNode* root)
{
  if (NULL == root)
  {
    return 0;
  }
  int left = TreeHeight(root->left);
  int right = TreeHeight(root->right);
  return  (left > right ? left : right) + 1;
}

栈帧空间的创建销毁顺序按照下图进行的,向右的箭头表示创建,向左的箭头表示销毁。创建销毁的顺序是橙色->绿色->蓝色->粉色->深蓝色->金色,最后结果为3。

32112009a06e460bb5c7b156f490e555.png


二叉树K层节点数

int TreeKLevelSize(BTNode* root, int k)
{
  if (NULL == root)
  {
    return 0;
  }
  if (1 == k)
  {
    return 1;
  }
  return TreeKLevelSize(root->left, k - 1) + TreeKLevelSize(root->right, k - 1);
}

栈帧空间的创建销毁顺序按照下图进行的,向右的箭头表示创建,向左的箭头表示销毁。创建销毁的顺序是橙色->绿色->蓝色->粉色->深蓝色->金色,最后结果为3。


3ee00ac59d1f4ce388891799aea8824c.png

查找值为X的节点

BTNode* TreeFind(BTNode* root, BTDataType x)
{
  if (NULL == root)
    return NULL;
  if (x == root->data)
    return root;
  BTNode* ret1 = TreeFind(root->left, x);
  if (ret1)
    return ret1;
  BTNode* ret2 = TreeFind(root->right, x);
  if (ret2)
    return ret2;
  return NULL;
}

栈帧空间的创建销毁顺序按照下图进行的,向右的箭头表示创建,向左的箭头表示销毁。创建销毁的顺序是橙色->绿色->蓝色->粉色->深蓝色->金色,最后结果为数字5节点的地址

d3c96c360e2f44a79e40fa41312bc161.png

判断二叉树是否为完全二叉树

bool TreeComplete(BTNode* root)
{
  Queue q;
  QueueInit(&q);
  if (root)
    QueuePush(&q, root);
  // 若队列为空,则不执行
  while (!QueueEmpty(&q))
  {
    BTNode* front = QueueFront(&q);
    QueuePop(&q);
    // 判断front是否为空,为空则跳出循环
    if (!front)
    {
      break;
    }
    else
    {
      QueuePush(&q, front->left);
      QueuePush(&q, front->right);
    }
  }
  // 若队列为空,则不执行
  while (!QueueEmpty(&q))
  {
    BTNode* front = QueueFront(&q);
    QueuePop(&q);
    if (front)
    {
      QueueDestroy(&q);
      return false;
    }
  }
  QueueDestroy(&q);
  return true;
}

二叉树的销毁

// 二叉树销毁
void TreeDestory(BTNode* root)
{
  if (NULL == root)
  {
    return;
  }
  TreeDestory(root->left);
  TreeDestory(root->right);
  free(root);
}
目录
相关文章
|
6天前
|
C语言
【数据结构】二叉树(c语言)(附源码)
本文介绍了如何使用链式结构实现二叉树的基本功能,包括前序、中序、后序和层序遍历,统计节点个数和树的高度,查找节点,判断是否为完全二叉树,以及销毁二叉树。通过手动创建一棵二叉树,详细讲解了每个功能的实现方法和代码示例,帮助读者深入理解递归和数据结构的应用。
35 8
|
29天前
|
存储 算法 关系型数据库
数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
这篇文章主要介绍了多路查找树的基本概念,包括二叉树的局限性、多叉树的优化、B树及其变体(如2-3树、B+树、B*树)的特点和应用,旨在帮助读者理解这些数据结构在文件系统和数据库系统中的重要性和效率。
17 0
数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
|
29天前
|
存储 算法 搜索推荐
数据结构与算法学习十七:顺序储存二叉树、线索化二叉树
这篇文章主要介绍了顺序存储二叉树和线索化二叉树的概念、特点、实现方式以及应用场景。
17 0
数据结构与算法学习十七:顺序储存二叉树、线索化二叉树
|
1月前
|
Java
【用Java学习数据结构系列】震惊,二叉树原来是要这么学习的(二)
【用Java学习数据结构系列】震惊,二叉树原来是要这么学习的(二)
26 1
|
1月前
|
算法 Java C语言
【用Java学习数据结构系列】震惊,二叉树原来是要这么学习的(一)
【用Java学习数据结构系列】震惊,二叉树原来是要这么学习的(一)
23 1
|
1月前
|
存储
【数据结构】二叉树链式结构——感受递归的暴力美学
【数据结构】二叉树链式结构——感受递归的暴力美学
|
1月前
|
存储 编译器 C++
【初阶数据结构】掌握二叉树遍历技巧与信息求解:深入解析四种遍历方法及树的结构与统计分析
【初阶数据结构】掌握二叉树遍历技巧与信息求解:深入解析四种遍历方法及树的结构与统计分析
|
1月前
|
存储 算法 调度
数据结构--二叉树的顺序实现(堆实现)
数据结构--二叉树的顺序实现(堆实现)
|
1月前
【高阶数据结构】二叉树进阶探秘:AVL树的平衡机制与实现详解(三)
【高阶数据结构】二叉树进阶探秘:AVL树的平衡机制与实现详解
|
1月前
【高阶数据结构】二叉树进阶探秘:AVL树的平衡机制与实现详解(二)
【高阶数据结构】二叉树进阶探秘:AVL树的平衡机制与实现详解

热门文章

最新文章