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

学习嵌入式的第二十四天——数据结构——队列和树

队列

做了限制线性表,在一端增长,在另外一端删除的线性表。 先进先出。

允许增加的一端,队尾,

允许删除的一端,队头

循环队列:

队空,head==tail 

满队 ,tail+1 == head;

作用: 做缓冲区(速度不匹配)

有n节点的有限集合。

根(最上面),叶子节点(最下面的节点),分支节点(中间节点)

树的度:结点中最大的度为树的度

树的高度:从当前节点到最远叶子节点的路径上的节点总数(叶子节点高度为 1,根节点高度等于二叉树的总高度)。

树的深度:从根节点到当前节点的路径上的节点总数(根节点深度为 1,叶子节点深度等于其层级)。

所有的N叉树都可以旋转成二叉树

二叉树,树的度为2. 

二叉树树的特性

任意二叉树,i层上最多有2^(i-1)个结点

深度为K的二叉树至多有2^k-1个结点

有n个结点的完全二叉树深度为(logn/log2)+1(向下取整)

所有类型的二叉树都满足:n=n0​+n1​+n2​
原因:总节点数 = 叶子节点数 + 1 子节点节点数 + 2 子节点节点数。

叶子节点数 = 2 子节点节点数 + 1(此公式对所有二叉树均成立,无论是否为特殊类型)。

完全二叉树的\(n_1\)只能是 0 或 1(因最后一层叶子节点靠左排列,不会出现 “单个子节点在右侧” 的情况):

若 n 为奇数(总节点数为奇):\(n_1 = 0\),则\(n_0 = (n + 1)/2\),\(n_2 = (n - 1)/2\);

若 n 为偶数(总节点数为偶):\(n_1 = 1\),则\(n_0 = n/2\),\(n_2 = n/2 - 1\)。

特殊的二叉树:斜树

满二叉树:除叶子节点外,所有内部节点都有 2 个子节点,且叶子节点都在同一层级。

1. 总节点数 = \(2^h - 1\)(h 为树的高度);
2. 叶子节点数 = \(2^{h-1}\)(占总节点数的一半);
3. 不存在仅含 1 个子节点的节点。

完全二叉树:按 “层序遍历顺序” 给节点编号(1~n,n 为总节点数),每个节点的编号都与满二叉树对应位置一致。青春版的满二叉树

二叉树的遍历

广度遍历(从上往下,从左往右)

void Levelordertrav(TreeNode* root, SeqQue* sq)
{if (root == NULL){return;}EnterSeqQue(sq, &root);DATATYPE data = 0;while (!IsEmptySeqQue(sq)){(data) = *GetHeadSeqQue(sq);QuitSeqQue(sq);printf("%c", data->data);if (NULL != data->left)EnterSeqQue(sq, &data->left);if (NULL != data->right)EnterSeqQue(sq, &data->right);}
}

深度遍历

用递归的方法:

前序(根左右)

void PreOrderTravel(TreeNode* root)
{if (NULL == root){return;}else{printf("%c", root->data);PreOrderTravel(root->left);PreOrderTravel(root->right);}
}

中序(左根右)

void MidOrderTravel(TreeNode* root)
{if (NULL == root){return;}else{MidOrderTravel(root->left);printf("%c", root->data);MidOrderTravel(root->right);}
}

后序(左右根)

void LastOrderTravel(TreeNode* root)
{if (NULL == root){return;}else{LastOrderTravel(root->left);LastOrderTravel(root->right);printf("%c", root->data);}
}

哈夫曼树

带权路径(WPL)最小的树

  1. 节点的权值(Weight)
    为每个节点赋予的一个 “数值属性”,代表该节点的 “重要性” 或 “出现频率”(如在数据压缩中,权值可表示字符的出现次数)。

  2. 路径长度(Path Length)
    从树的根节点到某一节点的路径上,所经过的 “边的数量”。例如:根节点到其直接子节点的路径长度为 1,到孙节点的路径长度为 2。

  3. 带权路径长度(Weighted Path Length, WPL)
    哈夫曼树的核心评价指标,分为节点的带权路径长度树的带权路径长度

    • 节点的带权路径长度 = 该节点的权值 × 根节点到该节点的路径长度;
    • 树的带权路径长度 = 所有叶子节点的带权路径长度之和(注意:内部节点的权值不参与计算,仅关注叶子节点)。

哈夫曼树的构建步骤

核心是 “每次选两个权值最小的节点合并”

  1. 初始化:生成初始叶子节点
    将所有给定的权值分别作为 “独立的节点”(每个节点均为叶子节点,无父节点和子节点),并将这些节点放入一个优先队列(最小堆) 中(便于快速获取权值最小的节点)。
    初始队列:[2, 3, 5, 7](堆顶为 2,权值最小)。

  2. 迭代合并:生成内部节点
    重复以下操作,直到队列中仅剩 1 个节点(即根节点):

    • 步骤 1:从队列中取出权值最小的两个节点(记为 A 和 B,A 的权值 ≤ B 的权值);
    • 步骤 2:创建一个新的内部节点 C,其权值 = A 的权值 + B 的权值;
    • 步骤 3:将 A 作为 C 的左子节点,B 作为 C 的右子节点(左、右顺序可互换,不影响 WPL,但影响后续编码);
    • 步骤 4:将新节点 C 放入优先队列中。

    以 {2, 3, 5, 7} 为例,具体合并过程:

    • 第 1 次合并:取 2(A)和 3(B)→ 生成 C(权值 5),队列变为 [5, 5, 7];
    • 第 2 次合并:取 5(A,新生成的 C)和 5(B,原叶子节点)→ 生成 D(权值 10),队列变为 [7, 10];
    • 第 3 次合并:取 7(A)和 10(B)→ 生成 E(权值 17),队列变为 [17](仅剩根节点,合并结束)。
  3. 最终结果
    队列中剩余的节点(权值 17)即为哈夫曼树的根节点,从根到叶子的路径构成完整的哈夫曼树(结构如前文示例中的树 2)。

哈夫曼编码

编码规则

基于构建好的哈夫曼树,为每个叶子节点(对应原始字符)分配二进制编码:

  • 从根节点出发,向左子树走记为 “0”向右子树走记为 “1”
  • 从根节点到某叶子节点的 “0/1 序列”,即为该叶子节点(字符)的哈夫曼编码。
http://www.xdnf.cn/news/18640.html

相关文章:

  • Git 提交除某个文件外的其他所有文件
  • 微信开发者工具:更改 AppID 失败
  • 嵌入式-EXTI的工作原理和按钮实验-Day19
  • 我从零开始学习C语言(13)- 循环语句 PART2
  • QT-窗口类部件
  • K8S高可用集群
  • K8s的相关知识总结
  • 如何理解面向过程和面向对象,举例说明一下?
  • Qt5 的跨平台开发详细讲解
  • 计算机毕设选题推荐 基于Spark的家庭能源消耗智能分析与可视化系统 基于机器学习的家庭能源消耗预测与可视化系统源码
  • 告别第三方流氓工具,如何实现纯净系统维护
  • DIC技术极端环境高温案例分享——从1600℃的锆合金力学性能测试到3000℃变形测试的DIC测量
  • 手机、电脑屏幕的显示坏点检测和成像原理
  • k8s----学习站点搭建
  • C++显示类型转换运算符static_cast使用指南
  • 贪吃蛇--C++实战项目(零基础)
  • 大模型微调:从理论到实践的全面指南
  • 【链表 - LeetCode】19. 删除链表的倒数第 N 个结点
  • Laravel 使用阿里云OSS S3 协议文件上传
  • Java多线程面试题二
  • Flask电影投票系统全解析
  • WPF控件随窗体大宽度高度改变而改变
  • 金融风控AI引擎:实时反欺诈系统的架构设计与实现
  • Rust 入门 注释和文档之 cargo doc (二十三)
  • AP服务发现PRS_SOMEIPSD_00255 的解析
  • 《WINDOWS 环境下32位汇编语言程序设计》第7章 图形操作(1)
  • UNIKGQA论文笔记
  • XP系统安装Android Studio 3.5.3并建立Java或Native C++工程,然后在安卓手机上运行
  • 算法题(188):团伙
  • Linux--进程核心概念