当前位置: 首页 > article >正文

【数据结构】剖析二叉树(Binary Tree)

目录

💯引言

💯二叉树的定义与基本概念

(一)定义

(二)节点结构

(三)二叉树的形态

💯二叉树的遍历

(一)前序遍历(Preorder Traversal)

(二)中序遍历(Inorder Traversal)

(三)后序遍历(Postorder Traversal)

(四)层序遍历(Level-order Traversal)

💯二叉树的应用

⭐搜索二叉树(Binary Search Tree)

⭐平衡二叉树(AVL Tree)

⭐其他应用

💯结论


💯引言

在计算机科学的数据结构领域中,二叉树是一种极为重要且应用广泛的结构。它就像一棵倒立的树,每个节点最多有两个分支,这种简单而又富有规律的结构为解决众多实际问题提供了高效的方法。

从文件系统的目录结构到数据库的索引,从算法设计中的搜索排序人工智能中的决策树二叉树都扮演着关键的角色

💯二叉树的定义与基本概念

(一)定义

二叉树(Binary Tree)是一种由节点组成的特殊数据结构。它由个节点构成的有限集合,当时,为空二叉树;当 n > 0 时满足以下条件:

  1. 有且仅有一个根节点。
  2. 每个节点最多有两棵子树,分别称为左子树右子树

(二)节点结构

二叉树的节点包含以下关键部分

  1. 数据域:用于存储节点所承载的数据信息。数据类型灵活多样,可以是整数、字符、结构体等,根据具体的应用需求而定。
  2. 左指针:指向该节点左子树的根节点。若左子树为空,则左指针的值为NULL
  3. 右指针:指向该节点右子树的根节点。同理,当右子树为空时,右指针为NULL

例如,在 C 语言中,二叉树节点结构体可定义为:

typedef struct TreeNode {
    int data;
    struct TreeNode *left;
    struct TreeNode *right;
} TreeNode;

(三)二叉树的形态

 

二叉树呈现出多种形态,各有其特点和应用场景

  1. 空二叉树:没有任何节点,是二叉树的初始状态,也是一种特殊情况,可形象地表示为一个空白的区域,象征着尚未填充数据的结构。
  2. 单节点二叉树:仅有一个节点,该节点既是根节点,也是整棵树的唯一元素。它就像一颗孤独的星星,在数据的天空中独自闪耀。
  3. 满二叉树:所有节点都满足度为2,即每个节点都有左右两个子节点,且所有叶子节点都在同一层。满二叉树在给定高度时,拥有最多的节点数,其节点总数2^{h}-1,其中 h 为树的高度。它是一种结构规整、对称美观的二叉树形态,像一个完美的晶体结构,蕴含着内在的平衡与规律。满二叉树如图
  4. 完全二叉树:对于一棵深度为、有个节点的二叉树,如果其节点编号从到与深度为的满二叉树中编号从到的节点位置完全相同。它在一定程度上结合了满二叉树的规整性和灵活性。 

        完全二叉树如图: 

 

💯二叉树的遍历

所谓二叉树遍历(Traversal)是按照某种特定的规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次遍历二叉树就像是在探索一座神秘的花园,依次访问每一个节点,以获取其中的数据或执行特定的操作。常见的遍历方式有以下几种:

(一)前序遍历(Preorder Traversal)

  1. 访问顺序:根节点 -> 左子树 -> 右子树。
    • 就像先探索花园的中心,然后向左扩展,最后向右延伸。
  2. 算法步骤
    • 首先访问根节点,输出其数据。
    • 然后递归地对左子树进行前序遍历。
    • 最后递归地对右子树进行前序遍历。
  3. 示例代码(以 C 语言为例)
void preorderTraversal(TreeNode *root) {
    if (root == NULL) {
        return;
    }
    printf("%d ", root->data);
    preorderTraversal(root->left);
    preorderTraversal(root->right);
}

 

(二)中序遍历(Inorder Traversal)

  1. 访问顺序:左子树 -> 根节点 -> 右子树。
    • 如同先深入花园的左侧,然后回到中心,最后探索右侧。
  2. 算法步骤
    • 首先递归地对左子树进行中序遍历。
    • 然后访问根节点,输出其数据。
    • 最后递归地对右子树进行中序遍历。
  3. 示例代码
void inorderTraversal(TreeNode *root) {
    if (root == NULL) {
        return;
    }
    inorderTraversal(root->left);
    printf("%d ", root->data);
    inorderTraversal(root->right);
}

从左子树开始,到根节点,再到右子树

 

(三)后序遍历(Postorder Traversal)

  1. 访问顺序:左子树 -> 右子树 -> 根节点。
    • 先探索花园的左右两侧,最后回到中心。
  2. 算法步骤
    • 首先递归地对左子树进行后序遍历。
    • 然后递归地对右子树进行后序遍历。
    • 最后访问根节点,输出其数据。
  3. 示例代码
void postorderTraversal(TreeNode *root) {
    if (root == NULL) {
        return;
    }
    postorderTraversal(root->left);
    postorderTraversal(root->right);
    printf("%d ", root->data);
}

先处理左右子树,最后访问根节点

 

(四)层序遍历(Level-order Traversal)

  1. 访问顺序:按照从根节点开始,从上到下、从左到右的顺序依次访问每一层的节点。
    • 就像一层一层地扫描花园,确保每一个角落都被探索到。
  2. 算法步骤
    • 使用一个队列来存储待访问的节点。
    • 首先将根节点入队。
    • 当队列不为空时,取出队首节点,访问该节点的数据。
    • 如果该节点有左子树,将左子树的根节点入队。
    • 如果该节点有右子树,将右子树的根节点入队。
  3. 示例代码
#include <stdio.h>
#include <stdlib.h>

typedef struct TreeNode {
    int data;
    struct TreeNode *left;
    struct TreeNode *right;
} TreeNode;

typedef struct QueueNode {
    TreeNode *data;
    struct QueueNode *next;
} QueueNode;

typedef struct Queue {
    QueueNode *front;
    QueueNode *rear;
} Queue;

void initQueue(Queue *q) {
    q->front = q->rear = NULL;
}

int isQueueEmpty(Queue *q) {
    return q->front == NULL;
}

void enqueue(Queue *q, TreeNode *data) {
    QueueNode *newNode = (QueueNode *)malloc(sizeof(QueueNode));
    newNode->data = data;
    newNode->next = NULL;
    if (isQueueEmpty(q)) {
        q->front = q->rear = newNode;
    } else {
        q->rear->next = newNode;
        q->rear = newNode;
    }
}

TreeNode *dequeue(Queue *q) {
    if (isQueueEmpty(q)) {
        printf("Queue is empty!\n");
        return NULL;
    }
    QueueNode *temp = q->front;
    TreeNode *data = temp->data;
    q->front = q->front->next;
    if (q->front == NULL) {
        q->rear = NULL;
    }
    free(temp);
    return data;
}

void levelOrderTraversal(TreeNode *root) {
    if (root == NULL) {
        return;
    }
    Queue q;
    initQueue(&q);
    enqueue(&q, root);
    while (!isQueueEmpty(&q)) {
        TreeNode *node = dequeue(&q);
        printf("%d ", node->data);
        if (node->left!= NULL) {
            enqueue(&q, node->left);
        }
        if (node->right!= NULL) {
            enqueue(&q, node->right);
        }
    }
}

  层序遍历如图: 

 

💯二叉树的应用

二叉树在计算机科学的各个领域都有着广泛的应用,以下是一些常见的例子:

⭐搜索二叉树(Binary Search Tree)

  1. 定义与特点:搜索二叉树是一种特殊的二叉树,对于树中的每个节点,其左子树中的所有节点的值都小于该节点的值,其右子树中的所有节点的值都大于该节点的值
    • 这种有序性使得在搜索二叉树中进行查找、插入和删除操作具有较高的效率。
  2. 查找操作:从根节点开始比较要查找的值与当前节点的值,如果要查找的值小于当前节点的值,则在左子树中继续查找;如果要查找的值大于当前节点的值,则在右子树中继续查找。
  3. 插入操作:同样从根节点开始比较要插入的值与当前节点的值,根据大小关系在合适的位置插入新节点。
  4. 删除操作:先找到要删除的节点,根据节点的情况进行不同的处理,如节点没有子节点、有一个子节点或有两个子节点等。

搜索二叉树如图: 

 

⭐平衡二叉树(AVL Tree)

  1. 定义与意义:平衡二叉树是一种特殊的二叉搜索树,要求任何节点的左右子树的高度差不超过 1 
    • 这种平衡特性可以保证在进行插入、删除等操作时,树的高度始终保持在较低的水平,从而提高操作的效率。
  2. 平衡调整算法:当树失去平衡时,通过左旋、右旋等操作来调整树的结构,使其重新满足平衡二叉树的定义。

平衡二叉树如图:

 

⭐其他应用

二叉树还可以用于表达式树、决策树等领域,在编译器设计、人工智能等方面发挥着重要作用。

 

💯结论

总之,二叉树以其简洁而强大的结构,成为了计算机科学领域中不可或缺的一部分。从基础的数据存储到高级的算法设计,它都发挥着至关重要的作用。我们应当珍视二叉树所带来的启示,不断学习和探索其更多的应用场景。


💝💝💝感谢你看到最后,点个赞再走吧!💝💝💝 

以下是一个投票,欢迎你参与,让我们一起了解大家对二叉树的认知和兴趣程度: 


http://www.kler.cn/a/320203.html

相关文章:

  • unity 打包WebGL打开后Input无法输入中文,在手机端无法调用输入法(使用WebGLInput)
  • Office-Tab-for-Mac Office 窗口标签化,Office 多文件标签化管理
  • android 使用MediaPlayer实现音乐播放--权限请求
  • 【多状态dp】买卖股票的最佳时机III
  • Leetcode 回文数
  • 多品牌摄像机视频平台EasyCVR视频融合平台+应急布控球:打造城市安全监控新体系
  • 低代码BPA(业务流程自动化)技术探讨
  • hive窗口函数实现组内求和、累加、排序、计数
  • Flutter路由
  • react crash course 2024(3) jsx语法及组件
  • mysql数据库:超键、候选键、主键与外键
  • 百度营销转化追踪(网页JS布码)
  • [Oracle] ORA-04036: 实例使用的 PGA 内存超出 PGA_AGGREGATE_LIMIT
  • [AIGC实战]5分钟使用EAS一键部署MLLM多模态大语言模型应用
  • 如何去编写一个好的单元测试,通义灵码是如何快速生成单元测试?
  • 免费的高质量、美观的甘特图模板
  • 求二叉树的高度(递归和非递归)
  • 【排序算法】选择排序、堆排序
  • 【数据结构之线性表】有序表的合并(链表篇)
  • 论文笔记:基于共注意网络的多模态假新闻检测
  • 基于组网分割的超大规模设计 FPGA 原型验证解决方案
  • power bi制作各季度收入累加柱状图——日期表、calculate、datesytd
  • Windows内核编程基础(2)
  • Ubuntu 20.04安装CMake 3.1
  • go fiber 证书
  • C语言 | Leetcode C语言题解之第437题路径总和III