哈夫曼树的学习以及实践

哈夫曼树

  • 哈夫曼树的基本了解
  • 哈夫曼树的基本概念
  • 创建霍夫曼树的思路
  • 编码构建的思路
  • 代码实现
    • 创建HuffmanTree结点
    • 初始化HuffmanTree
    • 创建霍夫曼树
    • 霍夫曼树编码

哈夫曼树的基本了解

给定 n 个 权值 作为 n 个 叶子节点,构造一颗二叉树,若该树的 带权路径长度(WPL)达到最小,称这样的二叉树为 最优二叉树,也称为 哈夫曼树(Huffman Tree),还有的叫 霍夫曼树

哈夫曼树的基本概念

  1. 路径 :从树中的一个结点到达另一个节点的分支结构构成的两个点之间的路径
  2. 路径长度:路径上的分支的数目(例如根结点为第一层,叶子节点为L层,那么根结点到叶子结点之间的路径长度为L-1)
  3. **树的路径长度:**从树的根结点到每个结点的路径长度之和
  4. :若将树中节点赋给一个有着某种函数的数值,则这个数值称为该节点的 权
  5. 结点的带权路径长度:从该结点到树根之间路径长度与该结点权重的乘积
  6. 树的带权路径长度:树中所有的叶子结点的带权路径长度之和
    在这里插入图片描述

创建霍夫曼树的思路

赫夫曼编码也翻译为 哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种 编码方式,,属于一种 程序算法
赫夫曼编码是 赫哈夫曼树 在电讯通信中的经典的应用之一。
赫夫曼编码广泛地用于 数据文件压缩。其压缩率通常在 20%~90% 之间
赫夫曼码是 可变字长编码(VLC) 的一种。Huffman 于 1952 年提出一种编码方法,称之为最佳编码
根据已经构建完成的赫夫曼树,给各个字符规定编码(前缀编码):
向左的路径为 0
向右的路径为 1

编码构建的思路

请添加图片描述
请添加图片描述

代码实现

创建HuffmanTree结点

#pragma region HuffmanTree的结构定义
typedef int datatype;
typedef struct HuffmanTree
{int weight;/*权重*/datatype data;int parent;int leftchild;int rightchild;
}HTNode;
typedef HuffmanTree* HuffTree;
#pragma endregion

初始化HuffmanTree

HuffTree InitHuffTree(int TreeNum)
{/*初始化树:首先创建存放2*TreeNum的存储空间的树,然后0下标位置不存放数据,从1位置开始赋值权重以及数据。*/HuffTree HT = NULL;HT = (HuffTree)malloc(sizeof(HTNode)*(2 * TreeNum));/*下标为0的HuffmanTree的结点是不用的*/for (int i = 1; i < 2*TreeNum; i++){HT[i].leftchild = -1;HT[i].rightchild = -1;HT[i].parent = -1;/*首先将双亲以及左右孩子置为-1*/}cout << "请输入权重" << endl;for (int i = 1; i <= TreeNum; i++){cin >> HT[i].weight;/*对每个结点赋值权重*/}char c = getchar();cout << "请输入数据" << endl;for (int i = 1; i <=TreeNum; i++){cin >> HT[i].data;}return HT;
}
#pragma endregion

创建霍夫曼树

void minvalue_select(HuffTree HT, int& minloction1, int& minloction2, int loc)
{int minvalue1 = MAXVALUE, minvalue2 = MAXVALUE;for (int i = 1; i < loc; i++){if ((minvalue1 > HT[i].weight)&&(HT[i].parent == -1)){minloction2 = minvalue1;minloction2 = minloction1;minvalue1 = HT[i].weight;minloction1 = i;}else{if ((HT[i].weight <minvalue2)&&(HT[i].parent == -1)){minvalue2 = HT[i].weight;minloction2 = i;}}}
}
HuffTree CreatHuffmanTree(HuffTree HT,int TreeNum)
{/*最终的parent为-1的结点代表根结点 没有双亲*/if (HT == NULL){cout << "HuffmanTree的数据为空 请重新输入" << endl;return NULL;}HuffTree tmpTree = NULL;tmpTree = HT;int minlocation1, minlocation2;for (int i = TreeNum+1; i <= TreeNum*2-1; i++){minvalue_select(tmpTree, minlocation1, minlocation2, i-1);/*找出两个最小的值*/HT[minlocation1].parent = HT[minlocation2].parent = i;HT[i].leftchild = minlocation1;HT[i].rightchild = minlocation2;/*其中location2大于location1*/HT[i].weight = HT[minlocation1].weight + HT[minlocation2].weight;}/*此时i也就是最后一个根结点 它的左右孩子已经确定 但是它的parent为-1 表示它为根结点*/return HT;
}
#pragma endregion

霍夫曼树编码

#pragma region 从叶子结点到根结点逆向求HuffmanTree编码
typedef char** HuffmanCode;
void HuffmanCoding(HuffTree HT, HuffmanCode& HC, int TreeNum)
{HC = (HuffmanCode)malloc(sizeof(char*)*TreeNum);/*表明HC是一个指针类型的变量,同时每一个指针存放的位置为一个char*类型的数据,也就表示HC是一个存放指针类型数据的指针数组*/if (HT==NULL){return;}char* tmpcode = (char*)malloc(sizeof(char)*TreeNum);if (tmpcode == NULL){return;}tmpcode[TreeNum -1 ] = '\0';HuffTree  tmpHTree = NULL;tmpHTree = HT;for (int i = 1; i <= TreeNum; i++){int location = TreeNum - 1;int parentIndex = tmpHTree[i].parent;int currentIndex = i;while (parentIndex !=-1)/*未到达根结点*/{if (tmpHTree[parentIndex].leftchild == currentIndex){tmpcode[--location] = '0';}else{tmpcode[--location] = '1';}currentIndex = parentIndex;parentIndex = tmpHTree[parentIndex].parent;}/*完成编码*/HC[i] = (char*)malloc(sizeof(char)*(TreeNum-location));if (HC[i]!=NULL){strcpy(HC[i], tmpcode + currentIndex);}cout << HC[i] << endl;}delete tmpcode;
}
#pragma endregion

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis相关介绍

概念 Redis&#xff1a;非关系型数据库&#xff08;non-relational)&#xff0c;Mysql是关系型数据库(RDBMS) Redis是当今非常流行的基于KV结构的作为Cache使用的NoSQL数据库 为什么使用NoSQL 关系型 数据库无法应对每秒上万次 的读写请求 表中的存储记录 数量有限 无法简单…

政安晨:在Jupyter中【示例演绎】Matplotlib的官方指南(四){Artist tutorial}·{Python语言}

第一次看到我的演绎文章的小伙伴&#xff0c;如果需要&#xff0c;可以先看一下我这篇文章的前三篇&#xff0c;包括准备环境等等&#xff1a; 政安晨&#xff1a;在Jupyter中【示例演绎】Matplotlib的官方指南&#xff08;一&#xff09;{Pyplot tutorial}https://blog.csdn.…

Vulnhub靶场 DC-8

目录 一、环境搭建 二、信息收集 1、主机发现 2、指纹识别 三、漏洞复现 1、SQL注入 sqlmap工具 2、dirsearch目录探测 3、反弹shell 4、提权 exim4 5、获取flag 四、总结 一、环境搭建 Vulnhub靶机下载&#xff1a; 官网地址&#xff1a;https://download.vulnhub.com/dc/DC-…

知识图谱 多模态学习 2024 最新综述

知识图谱遇见多模态学习&#xff1a;综述 论文题目&#xff1a;Knowledge Graphs Meet Multi-Modal Learning: A Comprehensive Survey 论文链接&#xff1a;http://arxiv.org/abs/2402.05391 项目地址&#xff1a;https://github.com/zjukg/KG-MM-Survey 备注&#xff1a;55…

读十堂极简人工智能课笔记01_人工智能简史

1. 2400年前 1.1. 希腊罗德岛 1.1.1. 是个神奇的岛屿&#xff0c;以机械发明著称&#xff0c;包括真人大小的、大理石制成的自动机 1.1.2. 早在罗马帝国诞生之前&#xff0c;公元前400多年的希腊就有这样的机器人技术&#xff0c;似乎不可思议 2. 公元前970到前931年 2.1.…

LAXCUS分布式操作系统目标:软件算力入口

英伟达现在的市值相当于整个中国股市&#xff01;说明了什么&#xff1f; AI 大潮下&#xff0c;算力就是生产力&#xff0c;也是未来 20 年一切产业的基础&#xff0c;英伟达已经把住硬件算力入口&#xff0c;LAXCUS 分布式操作系统瞄准软件算力入口&#xff0c;做好了&#…

网安常用的三个攻击方式

1.渗透测试执行标准&#xff08;PTES&#xff09; 渗透测试执行标准由7个部分组成&#xff0c;包括前期交互、情报收集、威胁建模、漏洞分析、渗透利用、后渗透、撰写报告。在中国&#xff0c;渗透测试必须经过授权&#xff0c;否则就违背了网络安全法。前期交互主要指开展渗透…

docker 1:介绍

docker 1&#xff1a;介绍 docker解决哪些问题&#xff1a; 传统APP在安装到不同电脑的时候可能会遇到依赖问题&#xff0c;比如缺少VS 20xx&#xff0c;软件无法运行”的情况。docker使用容器技术将软件 依赖​打包为image包发布&#xff0c;解决了依赖问题。docker有一个官…

腾讯云4核8G服务器性能如何?支持多少用户访问?

腾讯云4核8G服务器支持多少人在线访问&#xff1f;支持25人同时访问。实际上程序效率不同支持人数在线人数不同&#xff0c;公网带宽也是影响4核8G服务器并发数的一大因素&#xff0c;假设公网带宽太小&#xff0c;流量直接卡在入口&#xff0c;4核8G配置的CPU内存也会造成计算…

MySQL简单配置GTID

前期规划 IP地址 角色 系统版本 内核 软件包名称 192.168.2.3 Mysql主服务器 CentOS Stream 9 5.14.0- 381.el9.x86_64 mysql-8.2.0-linux-glibc2.17-x86_64.tar.xz 192.168.2.4 Mysql从服务器 CentOS Stream 9 5.14.0- 381.el9.x86_64 mysql-8.2.0-linux-glibc…

C语言—字符数组(3)

可能不是那么的完整&#xff0c;先凑合看吧&#xff0c;如果我学会如何修改以后&#xff0c;我慢慢回来修改的 1.编写程序实现对两个字符串的连接功能&#xff1b; 法一:不使用strcat函数,写程序直接实现&#xff0c;记得添加结束符&#xff0c;不然程序访问数组时候将变得不…