GDPU 数据结构 天码行空9

news/2025/2/14 4:11:47/

实验九 哈夫曼编码

一、【实验目的】

1、理解哈夫曼树的基本概念
2、掌握哈夫曼树的构造及数据结构设计
3、掌握哈夫曼编码问题设计和实现

二、【实验内容】

1、假设用于通信的电文仅由8个字母 {a, b, c, d, e, f, g, h} 构成,它们在电文中出现的概率分别为{ 0.07, 0.19, 0.02, 0.06, 0.32, 0.03, 0.21, 0.10 },试为这8个字母设计哈夫曼编码。

在这里插入图片描述

提示:包含两个过程:
(1)构建哈夫曼树
(2)输出编码。

三、【实验源代码】

#include <iostream>
using namespace std;
#include <cstdio>
#include <cstring>
typedef struct node {   //哈夫曼树中单个节点的信息int parent;   //父节点char letter;   //字母int lchild;int rchild;double weight;   //权值
}*HuffmanTree;
void Select(HuffmanTree& tree, int n, int& s1, int& s2) {   //找到权值最小的两个值的下标,其中s1的权值小于s2的权值int min = 0;for (int i = 1; i <= n; i++) {if (tree[i].parent == 0) {min = i;break;}}for (int i = min + 1; i <= n; i++) {if (tree[i].parent == 0 && tree[i].weight < tree[min].weight)min = i;}s1 = min;   //找到第一个最小值,并赋给s1for (int i = 1; i <= n; i++) {if (tree[i].parent == 0 && i != s1) {min = i;break;}}for (int i = min + 1; i <= n; i++) {if (tree[i].parent == 0 && i != s1 && tree[i].weight < tree[min].weight)min = i;}s2 = min;  //找到第二个最小值,并赋给s2
}
void CreateHuff(HuffmanTree& tree, char* letters, double* weights, int n) {int m = 2 * n - 1;   //若给定n个数要求构建哈夫曼树,则构建出来的哈夫曼树的结点总数为2n-1tree = (HuffmanTree)calloc(m + 1, sizeof(node));   //开辟空间顺序储存Huffman树,用calloc开辟的空间初始化的值为0(NULL),符合Huffman树初始化条件(parent、weight、lchild、rchild等初始化应为0),由于tree[0]不存数据(因为任何节点的父节点若为0,会与节点初始化0值相混淆,故不存数据),则要开辟(2n-1)+1个空间(额外开辟一个空间)for (int i = 1; i <= n; i++) {   //给节点赋字母及其对应的权值tree[i].weight = weights[i - 1];tree[i].letter = letters[i];}for (int i = n + 1; i <= m; i++) {int s1 = 0, s2 = 0;Select(tree, i - 1, s1, s2);   //每次循环选择权值最小的s1和s2,生成它们的父结点tree[i].weight = tree[s1].weight + tree[s2].weight;   //新创建的节点i 的权重是s1和s2的权重之和tree[i].lchild = s1;   //新创建的节点i 的左孩子是s1tree[i].rchild = s2;   //新创建的节点i 的右孩子是s2tree[s1].parent = i;   //s1的父亲是新创建的节点itree[s2].parent = i;   //s2的父亲是新创建的节点i}   
}
void HuffmanCoding(HuffmanTree& tree, char**& HuffCode, int n) {HuffCode = (char**)malloc(sizeof(char*) * (n + 1));   //运用char型二级指针,可理解成包含多个char*地址的数组,开n+1个空间,因为下标为0的空间不用char* tempcode = (char*)malloc(sizeof(char) * n);tempcode[n - 1] = '\0';for (int i = 1; i <= n; i++) {int start = n - 1;int doing = i;   //doing为正在编码的数据节点int parent = tree[doing].parent;   //找到该节点的父结点while (parent) {   //直到父结点为0(NULL),即父结点为根结点时停止if (tree[parent].lchild == doing)   //如果该结点是其父结点的左孩子,则编码为0,否则为1tempcode[--start] = '0';elsetempcode[--start] = '1';doing = parent;   //继续往上进行编码parent = tree[parent].parent;}HuffCode[i] = (char*)malloc(sizeof(char) * (n - start));   //开辟用于存储编码的内存空间strcpy(HuffCode[i], &tempcode[start]);   //将编码拷贝到字符指针数组中的相应位置}free(tempcode); //释放辅助空间
}
int main() {int n = 8;char letters[9] = {' ','a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};double weights[9] = {0.07, 0.19, 0.02, 0.06, 0.32, 0.03, 0.21, 0.10};HuffmanTree tree;CreateHuff(tree, letters, weights, n);   //构建哈夫曼树char** HuffCode;HuffmanCoding(tree, HuffCode, n);for (int i = 1; i <= n; i++)printf("字母 %c 的哈夫曼编码值是: %s\n", tree[i].letter, HuffCode[i]);return 0;
}

👨‍🏫 参考资料


http://www.ppmy.cn/news/1207616.html

相关文章

【JAVA学习笔记】67 - 坦克大战1.5 - 1.6,防止重叠,记录成绩,选择是否开新游戏或上局游戏,播放游戏音乐

项目代码 https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter20/src 增加功能 1.防止敌人坦克重叠运动 2.记录玩家的成绩&#xff0c;存盘退出 3.记录当时的敌人坦克坐标&#xff0c;存盘退出 4.玩游戏时&#xff0c;可以选择是开新游戏还是继续上局…

【星海出品】flask(三) 组件

Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架 wsgiref 因为我们不希望接触到TCP连接、HTTP原始请求和响应格式&#xff0c;所以&#xff0c;需要一个统一的接口协议来实现这样的服务器软件&#xff0c;让我们专心用Python编写Web业务。 这个…

【已解决】ModuleNotFoundError: No module named sklearn

这个问题比较简单&#xff0c;就简单记录如下&#xff1a; "ModuleNotFoundError: No module named sklearn" 错误表示你尝试导入名为 "sklearn" 的Python模块&#xff0c;但Python解释器找不到该模块。这通常是因为你尚未安装所需的Python库或模块。要解决…

Kibana使用Watcher监控服务日志并发送飞书报警(Markdown)

Watcher是什么 Kibana Watcher 是 Elasticsearch 的监控和告警工具&#xff0c;它允许你设置和管理告警规则以监控 Elasticsearch 数据和集群的状态。Kibana Watcher 可以监测各种指标和数据&#xff0c;然后在满足特定条件时触发警报。它提供了一种强大的方式来实时监控 Elas…

【ROS】Nav2源码之nav2_smoother(平滑器)详解

【ROS】郭老二博文之:ROS目录 1、简述 从路径规划模块’ nav2_planner 中给出路径通常是不平滑的。 所谓平滑器就是使规划的路径更平滑、平稳,可以运行的更优雅,并且减少硬件的磨损。 nav2_smoother在Nav2导航中的定义了平滑器接口的,nav2_smoother加载了一组平滑器插件,…

构建自己的插件框架:第 5 部分

文章目录 一、怪物插件1、动态C++插件2、静态C++插件3、动态C插件4、混合使用C/C++插件二、开始游戏本系列文章来自 Building Your Own Plugin Framework, 主要内容是讨论使用C/C++ 语言开发跨平台的插件框架所需要的架构、开发方法以及部署。我们将从分析现有插件/组件系统…

el-select配合el-tree实现下拉选以及数据回显以及搜索

一、前言 有时候就会遇到组件配合使用的情况&#xff0c;然后就整理了一下&#xff0c;后面大家需要的话可以直接拿去使用。 二、源码 <template><el-selectref"selectTree"filterablev-model"name":placeholder"请选择":filter-meth…

Java面试题-Redis-第四天(线程模型一)

目录 一、Redis为何选择单线程&#xff1f; 二、Redis真的是单线程吗&#xff1f; 三、Redis6.0为何引入多线程 四、Redis6.0引入多线程之后&#xff0c;性能的提升效果如何&#xff1f; 一、Redis为何选择单线程&#xff1f; 通常对于一个数据库来说&#xff0c;CPU通常不…