【数据结构与算法】哈夫曼编码(最优二叉树实现

news2024/11/24 8:56:03

哈夫曼编码

等长编码:占的位置一样

变长编码(不等长编码):经常使用的编码比较短,不常用的比较短

最优:总长度最短

最优的要求:占用空间尽可能短,不占用多余空间,且不能有二义性

这里给出哈夫曼二叉树的实现:

HuffmanTree.h:

#pragma once

template <typename T>
class HuffmanTree {
public:
    HuffmanTree(int nCount, T* InData, int* InWeight);
private:
    typedef struct _HuffNode {
        T tValue;
        int weight;
        int n_lChild;
        int n_rChild;
        int n_Father;
    }Tree, *pTree;
    pTree m_pTreeRoot;
    int nTreeCount;
public:
    void show();
    void HuffmanCode(char** &InHuffmanCode,int nCount);
private:
    void select(int nCount, int* SmallValueA_Index, int* SmallValueB_Index);
};

template<typename T>
inline HuffmanTree<T>::HuffmanTree(int nCount, T * InData, int* InWeight)
{
    nTreeCount = 2 * nCount;
    m_pTreeRoot = (pTree)calloc(nTreeCount + 1, sizeof(Tree));
    for (size_t i = 1; i <= nCount; i++) {
        m_pTreeRoot[i].tValue = InData[i-1];
        m_pTreeRoot[i].weight = InWeight[i-1];
    }
    for (size_t i = nCount + 1; i < nTreeCount; i++) {
        int SmallValueA_Index;
        int SmallValueB_Index;
        select(i - 1, &SmallValueA_Index, &SmallValueB_Index);
        m_pTreeRoot[SmallValueA_Index].n_Father = i;
        m_pTreeRoot[SmallValueB_Index].n_Father = i;
        m_pTreeRoot[i].n_lChild = SmallValueA_Index;
        m_pTreeRoot[i].n_rChild = SmallValueB_Index;
        m_pTreeRoot[i].weight = m_pTreeRoot[SmallValueA_Index].weight + m_pTreeRoot[SmallValueB_Index].weight;
        m_pTreeRoot[i].tValue = '0';
    }

}

template<typename T>
inline void HuffmanTree<T>::show()
{
    std::cout << "Index" << "   " << "Value" << "   " << "weight" << "   " << "ParentIndex" << "   " << "lChild" << "   " << "rChild" << "   " << std::endl;
    for (size_t i = 1; i < nTreeCount; i++) {
        printf("%-5.0d   %-5c   %-6d   %-11d   %-6d    %-6d\r\n", i, m_pTreeRoot[i].tValue, m_pTreeRoot[i].weight, m_pTreeRoot[i].n_Father, m_pTreeRoot[i].n_lChild, m_pTreeRoot[i].n_rChild); 
    }
}

template<typename T>
inline void HuffmanTree<T>::HuffmanCode(char **& InHuffmanCode, int nCount)
{
    InHuffmanCode = (char**)malloc(sizeof(char*)*(nCount + 1));
    char* code = (char*)malloc(nCount);
    code[nCount-1] = '\0';
    for (size_t i = 1; i <= nCount; i++) {
        int cha = i;
        int parent = m_pTreeRoot[i].n_Father;
        int start = nCount - 1;
        while (parent) {
            if (m_pTreeRoot[parent].n_lChild == cha) {
                code[--start] = '0';
            }
            else {
                code[--start] = '1';
            }
            cha = parent;
            parent = m_pTreeRoot[parent].n_Father;
        }
        InHuffmanCode[i] = (char*)malloc(nCount - start);
        strcpy(InHuffmanCode[i], &code[start]);
    }
}



template<typename T>
inline void HuffmanTree<T>::select(int nCount, int * SmallValueA_Index, int * SmallValueB_Index)
{
    int nMin;
    for (size_t i = 1; i < nCount; i++) {
        if (m_pTreeRoot[i].n_Father == 0) {
            nMin = i;
            break;
        }
    }
    for (size_t i = nMin + 1; i <= nCount; i++) {
        if (m_pTreeRoot[i].n_Father == 0 && m_pTreeRoot[i].weight < m_pTreeRoot[nMin].weight) {
            nMin = i;
        }
    }
    *SmallValueA_Index = nMin;
    for (size_t i = 1; i <= nCount; i++)
    {
        if (m_pTreeRoot[i].n_Father == 0 && i != *SmallValueA_Index)
        {
            nMin = i;
            break;
        }
    }
    for (size_t i = nMin + 1; i <= nCount; i++)
    {
        if (m_pTreeRoot[i].n_Father == 0 && m_pTreeRoot[i].weight < m_pTreeRoot[nMin].weight &&  i != *SmallValueA_Index)
        {
            nMin = i;
        }
    }
    *SmallValueB_Index = nMin;
}

测试数据(主函数):

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include "HuffmanTree.h"

int main() {
	char a[] = { 'A','B','C','D','E','F' };
	int b[] = { 5,32,18,7,25,13 };
	HuffmanTree<char> arr(6, a, b);
	arr.show();
	char** HuffmanCode = nullptr;
	arr.HuffmanCode(HuffmanCode,6);
	std::cout << "编码值:" << std::endl;
	for (size_t i = 1; i <= 6; i++)
	{
		printf("  %c:   %s\n",a[i-1],HuffmanCode[i]);
	}
	return 0;
}

运行结果截图:
哈夫曼二叉树
如果发现文章中有错误,还请大家指出来,我会非常虚心地学习,我们一起进步!!!

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

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

相关文章

4.BIO多线程即时通信

highlight: arduino-light 基于BIO模式下的即时通信&#xff0c;我们需要解决客户端到客户端的通信&#xff0c;也就是需要实现客户端与客户端的端口消息转发逻辑。 功能清单 1.客户端登陆功能 可以启动客户端进行登录&#xff0c;客户端登陆只需要输入用户名和服务端ip地址即可…

JVM理论(五)执行引擎--解释器/JIT编译器

概述 首先执行引擎是java虚拟机核心的组成部分之一;而JVM的主要任务是装载字节码到内存,但不能够直接运行在操作系统之上.因为字节码指令并非等价于本地机器指令,它仅仅包含能够被JVM所识别的指令、符号表、以及其他信息;而此时执行引擎就华丽登场,它的任务就是将字节码指令解…

欧姆龙PLC联网

一、设备信息确认 左上角的为PLC型号,如图该PLC型号为CP1H,不同型号的欧姆龙PLC通讯方面有什么差别呢? 通讯能力和方式不同: 有些型号PLC自带网口,有些则需要扩展(上图中右侧的两个红框内为后扩展的通讯口,扩展模块可以随意组合双网口,双232串口,双485串口都可以)…

D354周赛复盘:特殊元素平方和+数组最大美丽值(滑动窗口)+合法分割最小下标

文章目录 6889.特殊元素平方和思路完整版取模注意&#xff1a;不能对0取余/取模解答错误&#xff1a;本题的数组最后一个下标是nums[nums.size()] 6929.数组的最大美丽值&#xff08;排序滑动窗口&#xff09;思路1&#xff1a;排序滑动窗口注意点 6927. 合法分割的最小下标&am…

My_window类(带有next和quit按钮)

运行代码&#xff1a; //My_window类&#xff08;带有next和quit按钮&#xff09; #include"std_lib_facilities.h" #include"GUI/Simple_window.h" #include"GUI/GUI.h" #include"GUI/Graph.h" #include"GUI/Point.h"//--…

为什么项目可见性难以实现?该如何提高?

在项目和专业服务管理中&#xff0c;失败有时难以避免。沟通不足和需求定义不明确被认为是造成失败的最大原因&#xff0c;这意味着项目可见性和信息流动至关重要。 什么是项目可见性&#xff1f; 项目可见性是组织项目相关信息的方式&#xff0c;以便所有团队成员、项目经理…

火狐安卓版支持油猴了!后面将支持更多扩展插件

日前火狐浏览器每夜构建版的安卓版已经带来了更多扩展程序支持&#xff0c;这其中就包括大名鼎鼎的油猴扩展程序。本次火狐浏览器每夜构建版更新新增五款扩展程序支持&#xff0c;并且按照谋智基金会说法还会支持更多的扩展程序。 下载地址&#xff1a;https://ftp.mozilla.org…

力扣 406. 根据身高重建队列

题目来源&#xff1a;https://leetcode.cn/problems/queue-reconstruction-by-height/description/ C题解1&#xff1a;分别对h和k两个维度进行考虑&#xff0c;我这里是优先考虑k值&#xff0c;k值相同的时候h小的排前面。然后再一一遍历&#xff0c;对于people[i]&#xff0c…

曲师大2023大一新生排位赛-D.Factor题解

D.Factor 题目描述 你有一个集合 &#xff0c;和具有 个正整数的数组 . 最初&#xff0c;集合 为空&#xff08;不包含任一元素&#xff09;。你将按照以下方式填充集合 : 以此枚举数组 a 中的每个元素。对于数组中的第 i 个元素 &#xff0c;生成 ​ 的因子集合 ​。如果…

uniapp引入echarts

作为前端在开发需求的时候经常会遇到将数据展示为图表的需求&#xff0c;之前一直用的HBuilder的图表插件uCharts&#xff0c;使用方法可以参考我的另一篇博客&#xff1a;uniapp 中使用图表&#xff08;秋云uCharts图表组件&#xff09; 但是最近发现uCharts很多功能都需要付…

国密算法概述、及算法的集成应用(sm2、sm3、sm4)

国密算法概述、及算法的集成应用&#xff08;sm2、sm3、sm4&#xff09; 一、概述二、分类概述3.1、SM1对称密码3.2、SM2椭圆曲线公钥密码算法3.3、SM3杂凑算法3.4、SM4对称算法3.5、SM7对称密码3.6、SM9标识密码算法3.7、ZUC祖冲之算法 三、集成SM2加解密四、集成SM3加密、验签…

系统学习Linux-Rsync远程数据同步服务(三)

一、概述 rsync是linux 下一个远程数据同步工具 他可通过LAN/WAN快速同步多台主机间的文件和目录&#xff0c;并适当利用rsync 算法减少数据的传输 会对比两个文件的不同部分&#xff0c;传输差异部分&#xff0c;因此传输速度相当快 rsync可拷贝、显示目录属性&#xff0c…

将TXT转化为PDF的方法有哪些,分享四个给大家!

将TXT文本文件转换为PDF是一项常见的需求&#xff0c;特别是在需要共享文档时。在本文中&#xff0c;我们将分享四种方法&#xff0c;让您能够轻松地将TXT文件转换为PDF格式。 方法一&#xff1a;使用记灵在线工具 记灵在线工具是一个方便易用的在线文档转换工具&#xff0c;…

日撸java三百行day77-79

文章目录 说明GUI1. GUI 总体布局2. GUI 代码理解2.1 对话框相关控件2.1.1 ApplicationShowdown.java&#xff08;关闭应用程序&#xff09;2.1.2 DialogCloser.java&#xff08;关闭对话框&#xff09;2.1.3 ErrorDialog.java&#xff08;显示错误信息&#xff09;2.1.4 HelpD…

C++基础算法离散化及区间合并篇

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;C算法 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 主要讲解了双指针&#xff0c;位运算&#xff0c;离散化以及区间合并。…

店铺记账用什么软件好?应该如何选购?

店铺记账过程中&#xff0c;会遇到各种问题&#xff1a;手写记账容易出错、效率低下、数据容易丢失&#xff1b;手动整理数据导致实际库存和账面库存不匹配&#xff0c;影响补货和订单管理。 而借助专业的店铺记账软件&#xff0c;可以有效解决上面这些问题&#xff0c;通过自动…

51单片机学习--矩阵键盘、电子密码锁

矩阵键盘的模块原理图&#xff1a; 功能&#xff1a;按下矩阵按键&#xff0c;在LCD上显示对应的数值。 采用模块化编程&#xff0c;在此只给出MatrixKey.c 和 main.c 两部分代码 #include <REGX52.H> #include "Delay.h"/*矩阵键盘读取键码按下不放&#xf…

K8S集群内部署Rancher2.5.16

K8S集群内部署Rancher2.5.16 一、环境 k8s&#xff1a;1.18.20 OS&#xff1a;Anolis OS 7.9 rancher&#xff1a;2.5.16 参考官网部署文档&#xff1a;https://ranchermanager.docs.rancher.com/zh/v2.6/pages-for-subheaders/install-upgrade-on-a-kubernetes-cluster 二…

回归预测 | MATLAB实现基于SVM-Adaboost支持向量机结合AdaBoost多输入单输出回归预测

回归预测 | MATLAB实现基于SVM-Adaboost支持向量机结合AdaBoost多输入单输出回归预测 目录 回归预测 | MATLAB实现基于SVM-Adaboost支持向量机结合AdaBoost多输入单输出回归预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 1.MATLAB实现基于SVM-Adaboost支持向…

Meta发布升级大模型LLaMA 2:开源可商用

论文地址&#xff1a;https://ai.meta.com/research/publications/llama-2-open-foundation-and-fine-tuned-chat-models/ Github地址&#xff1a;https://github.com/facebookresearch/llama LLaMA 2介绍 Meta之前发布自了半开源的大模型LLaMA&#xff0c;自从LLaMA发布以来…