【GDPU】数据结构实验十 哈夫曼编码

news2024/11/24 11:50:54

【实验内容】


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)输出编码。


我的思路:

1建造哈夫曼树的过程直接按照哈夫曼思想模拟即可

2)输出编码。而 哈夫曼编码函数,我使用了 图论中的 dfs回溯算法 的思想,采用以 递归为 核心的方法遍历整棵树,并将走过的左路径标记为 0,将走过的右路径标记为 1,到了叶子节点收集路径结果,

每一条路径我使用 一维数组 path 记录

全部路径的结果,我使用 二维数组 result 存储

最后打印 result  数组即可


简而言之:

用一维数组记录路径 上的 0 和 1,到了叶子节点就成为一条完整的编码

将每一条编码用  二维数组 存起来


头文件 Head.h

建造一棵哈夫曼树的相关函数和操作

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#define MAX 40



// 创建树节点
typedef struct HtNode {
	int ww;
	int parent, Lchild, Rchild;
}HtNode;


// 哈夫曼树结构
typedef struct HtTree {
	int root;
	HtNode ht[MAX];
}PHtTree;



// 构造哈夫曼树
// m 为权值节点数量,w 为权值数组
PHtTree* CreateHuffMan(int m, int* w) {
	// 创建带有 m 个叶子节点的哈夫曼树
	PHtTree* pht = (PHtTree*)malloc(sizeof(PHtTree));
	if (pht == NULL) {
		perror("malloc fail !");
		return NULL;
	}

	// 初始化
	for (int i = 0; i < 2 * m - 1; ++i) {
		pht->ht[i].Lchild = pht->ht[i].Rchild = pht->ht[i].parent = -1;

		// 将数组前 m 个位置放入 权值数组元素
		if (i < m)
			pht->ht[i].ww = w[i];
		else
			pht->ht[i].ww = -1;
	}

	// 构建哈夫曼树
	int i;
	for (i = 0; i < m - 1; i++) {
		// 两个m 找最小权值,两个 index 记录这两节点的下标
		int m1, m2, index1, index2;
		m1 = m2 = INT_MAX;
		index1 = index2 = -1;

		// 每轮都在区间 [0,  m + i] 找两个最小权值节点,且没有父节点(即没有使用过)
		for (int j = 0; j < m + i; ++j) {
			if (pht->ht[j].ww < m1 && pht->ht[j].parent == -1) {
				m2 = m1;
				index2 = index1;
				m1 = pht->ht[j].ww;
				index1 = j;
			}
			else if (pht->ht[j].ww < m2 && pht->ht[j].parent == -1) {
				m2 = pht->ht[j].ww;
				index2 = j;
			}
		}

		// 找到节点之后,构建父节点,并将父节点放进数组中
		pht->ht[index1].parent = m + i;
		pht->ht[index2].parent = m + i;
		pht->ht[m + i].ww = m1 + m2;
		pht->ht[m + i].Lchild = index1;
		pht->ht[m + i].Rchild = index2;
	}

	pht->root = m + i; // 更新根节点:m+i 即为 m + (m-2)
	return pht;
}

哈夫曼编码函数  HuffmanEncode

#include"Head.h"


// 哈夫曼编码
// 思路:遍历每一条路,到叶子节点记录结果,左边标记为 0, 右边标记为 1


// p  遍历 path :从下标 1 开始存放编码串,下标 0 存放字符串长度(表示该编码串长度,方便遍历)
// r 遍历 result:代表一一存放结果
int r = 0, p = 1;  
int result[MAX][MAX];  // 收集 path 的每一次结果
int path[MAX];   // 记录每一条路径的编码

void HuffmanEncode(HtNode* ht, int root)
{
	if (root == -1) return; // 空节点返回
	if (ht[root].Lchild == -1 && ht[root].Rchild == -1) { // 叶子节点 就记录结果
		path[0] = p - 1;  // p-1 代表此时 path数组中收集的 路径上的(一串 1 和 0)的数量:方便遍历,因为每一串编码不等长,所以需要记录数量
		memcpy(result + r, path, sizeof(int)*p);  // 将一维数组 path 存放进二维数组 result :记录每一条路径的最终结果
		r++;
		path[0] = 0;  // 将第 0 个位置重新置为 0(表示恢复之前的状态)
		return;
	}


	path[p++] = 0;  // 向左走路径标记为 0
	HuffmanEncode(ht, ht[root].Lchild); // 递归到左节点
	p--;  // 从左节点回退回来:p-- 代表将 path[p++] = 0;   这里曾经标记的 0 给"删除"


	path[p++] = 1;  // 路径标记为 1
	HuffmanEncode(ht, ht[root].Rchild); // 递归到右节点
	p--;   // 从右节点回退回来:p-- 代表将 path[p++] = 1;   这里曾经标记的 1 给"删除"

}

主函数 Main.c 



int main()
{
	// 输入 m 和 w 数组
	int m, w[MAX];
	scanf("%d", &m);
	float t = 0;
	for (int i = 0; i < m; ++i) {
		scanf("%f", &t);
		w[i] = t * 100;  // 浮点树先乘上倍数,变成整型,方便计算
	}

	// 构建一棵树
	PHtTree* pht = CreateHuffMan(m, w);


	HuffmanEncode(pht->ht, pht->root - 1); // 传数组过去就可以了


	// 打印每一编码
	printf("\n");
	for (int i = 0; i < m; ++i) {
		int x = result[i][0];
		for (int j = 1; j <= x; ++j) {
			printf("%d ", result[i][j]);
		}
		printf("\n");
	}

	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1649285.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

突破传统 重新定义:3D医学影像PACS系统源码(包含RIS放射信息)实现三维重建与还原

突破传统&#xff0c;重新定义PACS/RIS服务,洞察用户需求&#xff0c;关注应用场景&#xff0c;新一代PACS/RIS系统&#xff0c;系统顶层设计采用集中分布式架构&#xff0c;满足医院影像全流程业务运行,同时各模块均可独立部署&#xff0c;满足医院未来影像信息化扩展新需求、…

运动控制“MC_MoveVelocity“功能块详细应用介绍

1、运动控制单位u/s介绍 运动控制单位[u/s]介绍-CSDN博客文章浏览阅读91次。运动控制很多手册上会写这样的单位,这里的u是英文单词unit的缩写,也就是单位的意思,所以这里的单位不是微米/秒,也不是毫米/秒,这里是一个泛指,当我们的单位选择脉冲时,它就是脉冲/秒,也就是…

java--GUI

目录 GUI&#xff08;Graphical User Interface&#xff09; swing 窗口(JFrame) 面板(JPanel) 流水布局(FlowLayout) 边界布局(BorderLayout) ​编辑 网格布局(GridLayout) 按钮(JButton) 标签组件&#xff0c;用来设置文字(JLabel) 单行文本框组件(JTextField) 多…

高实时、高可靠的微内核操作系统——鸿道Intewell

近年来&#xff0c;我国不断推进工业转型升级&#xff0c;力求实现从传统工业大国向现代工业强国的跨越。想要在新一轮科技革命中“超车”&#xff0c;需要从多个维度进行深度布局和全面发力。 ——科技创新是核心驱动力 积极推动工业结构的优化和升级&#xff0c;通过发展新…

全新拼团模式 你一定没见过 白拿产品还有收益!

在七星拼团模式中&#xff0c;奖励制度是其核心吸引力之一。今天&#xff0c;我们将深入探讨这一模式的三种奖励&#xff1a;直推奖、滑落奖和出局奖&#xff0c;以及它们背后的互助机制。 奖励规则概述 首先&#xff0c;让我们了解一下奖励的具体规则。假设商品售价为499元&a…

【MM32F3270 Micropython】pwm输出

文章目录 前言一、PWM脉宽调制技术介绍二、machine.PWM 类2.1 machine.PWM 类的构造对象2.2 PWM 对象初始化2.3 关闭PWM设备2.4 设置pwm的周期2.5 设置占空比 三、pwm示例代码总结 前言 MicroPython是一种精简的Python 3编程语言实现&#xff0c;旨在在微控制器和嵌入式系统上…

突破AI迷雾:英特尔携手星环科技打造向量数据库革新方案,直降大模型幻觉

去年爆火的大模型&#xff0c;正在从百模大战走向千行百业落地应用。不过行业数据规模有限&#xff0c;企业数据隐私安全的要求等等因素&#xff0c;都让行业大模型的准确率面临挑战。近期发布的《CSDN AI 开发者生态报告》数据显示&#xff0c;“缺乏数据/数据质量问题”在大模…

RS2103XH 功能和参数介绍及规格书

RS2103XH 是一款单刀双掷&#xff08;SPDT&#xff09;模拟开关芯片&#xff0c;主要用于各种模拟信号的切换和控制。下面是一些其主要的功能和参数介绍&#xff1a; 主要功能特点&#xff1a; 模拟信号切换&#xff1a;能够连接和断开模拟信号路径&#xff0c;提供灵活的信号路…

set_input_delay的理解

1&#xff0c;set_input_delay约束理解 input_delay是指输入的数据到达FPGA的pad引脚时相对于时钟边沿的延迟有多大&#xff0c;单位是ns&#xff0c;数值可以是正&#xff0c;也可以是负。通过set_input_delay约束告诉编译器输入时钟和输入数据的相位关系。如下图所示假设时钟…

uniapp的app端软件更新弹框

1&#xff1a;使用html PLUS实现&#xff1a;地址HTML5 API Reference (html5plus.org)&#xff0c;效果图 2&#xff1a;在app.vue的onLaunch生命周期中&#xff0c;代码如下&#xff1a; onLaunch: function() {let a 0let view new plus.nativeObj.View(maskView, {backg…

PyRun_SimpleString(“import cv2“); 报错解决

#include <Python.h> #include <iostream>using namespace std;int main() {Py_Initialize();if (!Py_IsInitialized()){printf("初始化失败&#xff01;");return 0;}PyRun_SimpleString("import sys");PyRun_SimpleString("sys.path.ap…

【大模型】LLaMA-1 模型介绍

文章目录 一、背景介绍二、模型介绍2.1 模型结构2.2 模型超参数2.3 SwiGLU 三、代码分析3.1 模型结构代码3.2 FairScale库介绍 四、LLaMA家族模型4.1 Alpaca4.2 Vicuna4.3 Koala(考拉)4.4 Baize (白泽)4.5 Luotuo (骆驼&#xff0c;Chinese)4.6 其他 参考资料 LLaMA&#xff08…

本地运行AI大模型简单示例

一、引言 大模型LLM英文全称是Large Language Model&#xff0c;是指包含超大规模参数&#xff08;通常在十亿个以上&#xff09;的神经网络模型。2022年11月底&#xff0c;人工智能对话聊天机器人ChatGPT一经推出&#xff0c;人们利用ChatGPT这样的大模型帮助解决很多事情&am…

如何将 ONLYOFFICE 协作空间服务器版更新至 2.5

最近我们发布了 ONLYOFFICE 协作空间 2.5 云端版。好消息&#xff0c;该文档协作平台的自托管版本也已推出。现在&#xff0c;您可以轻松更新协作空间的实例&#xff0c;在本地尝试所有新功能。阅读本文了解更多信息。 ONLYOFFICE 协作空间 2.5 新功能 更新到 ONLYOFFICE 协作…

Type-C转音频(USB2.0数据传输)+PD充电芯片乐得瑞LDR6500/LDR6023

LDR6500 USB-C DRP 接口 USB PD 通信芯片概述 Type-C转音频(USB2.0数据传输)PD充电芯片乐得瑞LDR6500LDR6500是乐得瑞科技针对USB Type-C标准中的Bridge设备而开发的USB-C DRP&#xff08;Dual Role Port&#xff0c;双角色端口&#xff09;接口USB PD&#xff08;Power Deliv…

彻底解决python的pip install xxx报错(文末附所有依赖文件)

今天安装pip install django又报错了&#xff1a; C:\Users\Administrator>pip install django WARNING: Ignoring invalid distribution -ip (d:\soft\python\python38\lib\site-pac kages) Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple Collecting djan…

redis持久化存储

Redis的持久化机制 Redis是一个基于内存的数据库&#xff0c;它的数据是存放在内存中&#xff0c;内存有个问题就是关闭服务或者断电会丢失。Redis的数据也支持写到硬盘中&#xff0c;这个过程就叫做持久化。 Redis提供如下两种持久化方式 RDB&#xff08;Redis DataBase&am…

【计算机毕业设计】基于SSM++jsp的网络游戏公司官方平台系统【源码+lw+部署文档+讲解】

目录 第1章 绪论 1.1 课题背景 1.2 课题意义 1.3 研究内容 第2章 开发环境与技术 2.1 MYSQL数据库 2.2 JSP技术 2.3 SSM框架 第3章 系统分析 3.1 可行性分析 3.1.1 技术可行性 3.1.2 经济可行性 3.1.3 操作可行性 3.2 系统流程 3.2.1 操作流程 3.2.2 登录流程 3.2.3 删除信息流…

我写了一套几乎无敌的参数校验组件!基于 SpEL 的参数校验组件「SpEL Validator」

前言 大家好&#xff0c;我是阿杆&#xff0c;不是阿轩。 参数校验这个东西&#xff0c;很多情况下都是比较简单的&#xff0c;用 NotNull、Size 等注解就可以解决绝大多数场景&#xff0c;但也有一些场景是这些基本注解解决不了的&#xff0c;只能用一些其他的方式处理&…

【极速前进】20240423-20240428:Phi-3、fDPO、TextSquare多模态合成数据、遵循准则而不是偏好标签、混合LoRA专家

一、Phi-3技术报告 论文地址&#xff1a;https://arxiv.org/pdf/2404.14219 ​ 发布了phi-3-mini&#xff0c;一个在3.3T token上训练的3.8B模型。在学术基准和内部测试中的效果都优于Mixtral 8*7B和GPT-3.5。此外&#xff0c;还发布了7B和14B模型phi-3-small和phi-3-medium。…