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

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

队列

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

允许增加的一端,队尾,

允许删除的一端,队头

循环队列:

队空,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.dtcms.com/a/344218.html

相关文章:

  • Flutter 从入门到精通 - 完整课程总结
  • 打印机怎么连接电脑?打印机驱动?【图文详解】USB连接打印机?wifi连接打印机?
  • ZKmall模块商城的跨境电商支付安全方案:加密与权限的双重防护
  • STL关联式容器解析:map与set详解
  • 电脑芯片大的32位与64位指的是什么
  • 94. 城市间货物运输 I, Bellman_ford 算法
  • 解读商业智能BI,数据仓库中的元数据
  • Python训练营打卡Day40-简单CNN
  • memcmp 函数的使用及其模拟实现
  • io.github.lucksiege:pictureselector状态栏没沉浸问题
  • 十大麦克风品牌排行榜,顶级麦克风品牌排行榜,麦克风品牌排行榜
  • 同济北化工联手AM:800 ℃/20 s磁感应闪焊合金负极,金属电池枝晶终结者
  • 一洽客服系统:自定义渠道启用路由和样式设置
  • 【自用】Maven常用依赖
  • AI知识管理全面指南:助力企业高效协作与创新
  • 【STM32】CubeMX(十一):FreeRTOS任务挂起与解挂
  • 汽车行业AI视觉检测方案(四):管控发动机外观缺陷
  • 【网卡配置编辑器】快捷的编辑网卡配置,便于调试网络设备
  • DOLO 上涨:Berachain 生态爆发的前奏?
  • 怎么用pytorch训练一个模型,并跑起来
  • More Effective C++ 条款02:最好使用C++转型操作符
  • JMeter 安装教程:轻松开启性能测试之旅
  • 前后端分离项目(Web篇)
  • BlockingQueue 是什么?
  • MySQL连接原理深度解析:从算法到源码的全链路优化
  • 微信扫码登陆 —— 接收消息
  • 关于日本服务器的三种线路讲解
  • 【Day01】堆与字符串处理算法详解
  • SHA 系列算法教程
  • C++ STL 中算法与具体数据结构分离的原理