跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C算法

数据结构:二叉树与堆

树与二叉树的基本概念、性质及存储结构,重点讲解了完全二叉树与堆的定义。内容涵盖树的表示法(如孩子兄弟表示法)、满二叉树与完全二叉树的区别,以及二叉树的顺序和链式存储。最后通过 C 语言实现了堆的数据结构,包括建堆、插入(向上调整)和删除(向下调整)算法的核心逻辑。

内存管理发布于 2026/3/24更新于 2026/9/6600 浏览
数据结构:二叉树与堆

1. 二叉树的概念

1.1 树的概念与结构

树有一个根节点,然后生出两个枝,一个枝又长出两个枝,并且每个枝最多长出两个枝。

  • 有一个特殊的节点,叫做根节点,他没有前驱节点
  • 除根结点外,其余结点被分成 M(M>0) 个互不相交的集合 T1、T2、……、Tm ,其中每一个集合 Ti(1 <= i <= m) 又是一棵结构与树类似的子树。每棵子树的根结点有且只有一个前驱,可以有 0 个或多个后继。因此,树是递归定义的。

子树之间是不能有交集的

1.2 树的相关术语

  • 父结点/双亲结点:若一个结点含有子结点,则这个结点称为其子结点的父结点;
  • 子结点/孩子结点:一个结点含有的子树的根结点称为该结点的子结点;
  • 结点的度:一个结点有几个孩子,他的度就是多少;树的度:一棵树中,最大的结点的度称为树的度;
  • 叶子结点/终端结点:度为 0 的结点称为叶结点;
  • 分支结点/非终端结点:度不为 0 的结点;
  • 兄弟结点:具有相同父结点的结点互称为兄弟结点;
  • 结点的层次:从根开始定义起,根为第 1 层,根的子结点为第 2 层,以此类推;
  • 树的高度或深度:树中结点的最大层次;
  • 结点的祖先:从根到该结点所经分支上的所有结点;
  • 路径:一条从树中任意节点出发,沿父节点 - 子节点连接,达到任意节点的序列;
  • 子孙:以某结点为根的子树中任一结点都称为该结点的子孙。
  • 森林:由 m(m>0)棵互不相交的树的集合称为森林;

1.3 树的表示

孩子兄弟表示法:树结构相对线性表就比较复杂了,要存储表示起来就比较麻烦了,既然保存值域,也要保存结点和结点之间的关系,实际中树有很多种表示方式如:双亲表示法,孩子表示法、孩子双亲表示法以及孩子兄弟表示法等。这里就简单的了解其中最常用的孩子兄弟表示法。

struct TreeNode {
    struct Node* child; // 左边开始的第一个孩子结点
    struct Node* brother; // 指向其右边的下一个兄弟结点
    int data; // 结点中的数据域
};

1.4 树形结构实际运用场景

文件系统是计算机存储和管理文件的一种方式,它利用树形结构来组织和管理文件和文件夹。在文件系统中,树结构被广泛应用,它通过父结点和子结点之间的关系来表示不同层级的文件和文件夹之间的关联。

2. 二叉树

2.1 概念与结构

在树形结构中,我们最常用的就是二叉树,一棵二叉树是结点的一个有限集合,该集合由一个根结点加上两棵别称为左子树和右子树的二叉树组成或者为空。

从上图可以看出二叉树具备以下特点:

    1. 二叉树不存在度大于 2 的结点
    1. 二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树

2.2 特殊的二叉树

2.2.1 满二叉树

满二叉树和名字一样,就是每层的节点数都到达最大数。

一个二叉树,如果每一层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为 K,且结点总数是 2^k-1.

2.2.2 完全二叉树

完全二叉树和满二叉树又不同,完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为 K 的,有 n 个结点的二叉树,当且仅当其每一个结点都与深度为 K 的满二叉树中编号从 1 至 n 的结点一一对应时称之为完全二叉树。要注意的是满二叉树是一种特殊的完全二叉树。

2.3 二叉树存储结构

2.3.1 顺序结构

无非就创建一个数组,挨个存二叉树的数据,根节点无疑是 0,然后他的两个孩子节点就是 1 和 2,1 的两个孩子节点就是 4 和 5,以此类推。

2.3.2 链式结构

链式结构更容易想象到,就是每个节点有两个指向,一个指向左孩子,一个指向右孩子,然后每个节点都存储数据。

3. 实现顺序结构二叉树

顺序结构实现二叉树一般使用堆的方式,

堆又分为大堆和小堆

  • 小堆:根节点是最小的数据,每个节点都比他的父节点大
  • 大堆:和小堆刚相反,根节点最大,每个节点都比父节点小

并且堆是一种完全二叉树

3.1 堆的实现

头文件 Heap.h

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int HPDataType;
typedef struct Heap {
    HPDataType* arr;
    int size;
    int capacity;
}HP;
void HPInit(HP* php);
void HPPush(HP* php,HPDataType x);
void HPPop(HP* php);
void HPDestory(HP* php);
bool HPEmpty(HP* php);

Heap.c

#include"Heap.h"

void HPInit(HP* php) {
    php->arr = NULL;
    php->capacity = 0;
    php->size = 0;
}

void Swap(int* x, int* y) {
    int tmp = *x;
    *x = *y;
    *y = tmp;
}

void AdjustUp(HP* php) {
    int child = php->size - 1;
    int parent = (php->size - 1) / 2;
    while (child > 0) {
        if (php->arr[parent] > php->arr[child]) {
            Swap(&php->arr[parent], &php->arr[child]);
            child = parent;
            parent = (child - 1) / 2;
        } else {
            break;
        }
    }
}

void HPPush(HP* php, HPDataType x) {
    assert(php);
    //判断空间是否足够
    if (php->size == php->capacity) {
        //扩容
        int newCapacity = php->capacity == 0 ? 4 : 2 * php->capacity;
        HPDataType* tmp = (HPDataType*)realloc(php->arr, newCapacity * sizeof(HPDataType));
        if (tmp == NULL) {
            perror("realloc fail!");
            exit(1);
        }
        php->arr = tmp;
        php->capacity = newCapacity;
    }
    php->arr[php->size] = x;
    AdjustUp(php);
    ++php->size;
}

void AdjustDown(HP* php) {
    int parent = 0;
    int child = 2 * parent + 1;
    while (child < php->size) {
        if (child + 1 < php->size && php->arr[child] > php->arr[child + 1]) {
            child++;
        }
        if (php->arr[parent] > php->arr[child]) {
            Swap(&php->arr[parent], &php->arr[child]);
            parent = child;
            child = parent * 2 + 1;
        } else {
            break;
        }
    }
}

void HPPop(HP* php) {
    Swap(&php->arr[0], &php->arr[php->size-1]);
    --php->size;
    AdjustDown(php);
}

bool HPEmpty(HP* php) {
    assert(php);
    return php->size == 0;
}

void HPDestory(HP* php) {
    if (php->arr) free(php->arr);
    php->arr = NULL;
    php->size = php->capacity = 0;
}

3.2 向下调整算法

就是在删除堆顶的时候,将堆顶与最后一个元素进行交换,然后 php->size--,从根节点挨个开始比较下一个节点的大小。

目录

  1. 1. 二叉树的概念
  2. 1.1 树的概念与结构
  3. 1.2 树的相关术语
  4. 1.3 树的表示
  5. 1.4 树形结构实际运用场景
  6. 2. 二叉树
  7. 2.1 概念与结构
  8. 2.2 特殊的二叉树
  9. 2.2.1 满二叉树
  10. 2.2.2 完全二叉树
  11. 2.3 二叉树存储结构
  12. 2.3.1 顺序结构
  13. 2.3.2 链式结构
  14. 3. 实现顺序结构二叉树
  15. 3.1 堆的实现
  16. 3.2 向下调整算法

更多推荐文章

查看全部
  • VSCode Copilot 自定义指令配置与开发效率提升实践
  • Windows 下 Nginx 配置指南:Vue 前端与后端服务一体化部署
  • 解密微信视频号 WebAssembly 加密:从逆向到实现
  • Linux 是什么与如何学习
  • 多模态模型开发实战:文本、图像与语音融合指南
  • 微软发布 AutoDev AI 程序员,自主完成软件工程任务性能提升 30%
  • Android Layout Weight 属性原理及正确用法
  • 高校毕业论文知网 AIGC 检测标准及降低 AI 率方法
  • Dify工作流集成TTS:低代码实现语音输出
  • Linux 进程控制详解:fork、wait 与退出机制
  • 人工智能(AI)常见面试题及答案汇总
  • PaddleOCR-VL-WEB 核心优势与本地部署推理教程
  • 突破 LLM 上下文瓶颈:上下文内存虚拟化 CMV 的设计与实践
  • 飞秋与 iptux 实现 Windows 及 Linux 内网跨平台通讯
  • CTFSHOW 元旦水友赛漏洞解析:PHP 反序列化至 RCE 实战
  • ARINC 825:航空电子 CAN 总线通信标准详解
  • 【面试分享】前端 React 50个基础高频面试题,助你轻松拿 offer!
  • 剑指 Offer 第 2 版:链表核心算法实战解析
  • Python 使用 Tesseract 实现 OCR 文字识别全流程指南
  • Python 实现 AI 大模型智能对话系统

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online