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

news2024/11/28 12:11:18

哈夫曼编码

等长编码:占的位置一样

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

最优:总长度最短

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

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

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/776157.html

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

相关文章

【MySQL】DML数据操纵语言(非常适合MySQL初学者学习)

&#x1f9d1;‍&#x1f4bb;作者名称&#xff1a;DaenCode &#x1f3a4;作者简介&#xff1a;啥技术都喜欢捣鼓捣鼓&#xff0c;喜欢分享技术、经验、生活。 &#x1f60e;人生感悟&#xff1a;尝尽人生百味&#xff0c;方知世间冷暖。 &#x1f4d6;所属专栏&#xff1a;重…

清华大学携手蚂蚁集团,攻坚可信AI、安全通用大模型等关键技术

2023年4月7日&#xff0c;清华大学与蚂蚁集团签署合作协议&#xff0c;双方将在“下一代互联网应用安全技术”方向展开合作&#xff0c;聚焦智能风控、反欺诈等核心安全场景&#xff0c;携手攻坚可信AI、安全大模型等关键技术&#xff0c;并加速技术落地应用&#xff0c;以解决…

NodeJS内置模块 npm包管理工具 nvm版本管理工具 nrm镜像管理工具

Nodejs 下载 下载地址 node 是什么 node.js 是一个开源的&#xff0c;跨平台的 JavaScript 运行环境 运行 js 文件 node 文件.jsnodemon 监听文件变化 npm i nodemon -gnodemon 文件名全局变量 global globalThis node 中顶级对象为 global &#xff0c;也可以使用 glo…

postgreSQL数据库的安装

文章目录 一、Linux 下安装 postgreSQL 数据库1.1、准备环境1.2、关闭防火墙跟SELinux1.2.1、关闭防火墙 firewalld1.2.2、关闭SELinux 1.3、挂载本地镜像1.4、软件包的下载postgreSQL 一、Linux 下安装 postgreSQL 数据库 1.1、准备环境 操作系统IP应用Red Hat 8192.168.192…

类加载的过程(简单介绍)

目录 一、类加载过程一览 加载&#xff1a; 验证&#xff1a; 准备&#xff1a; 解析&#xff1a; 初始化&#xff1a; 二&#xff1a;类加载器分类 启动类加载器&#xff08;bootstrap class loader&#xff09; 扩展类加载器&#xff08;extensions class loader&…

Nginx外网访问内网如何实现

1、背景 项目要求&#xff1a;将甲方内网的项目能够对外访问&#xff0c;甲方提供一个中间过渡服务器&#xff0c;中间过渡服务器与外网互通&#xff0c;且中间服务器可以访问内网&#xff1b; 外网客户端->中间过渡服务器开放端口&#xff1a;80 中间过渡服务器->内网服…

Cadence Allegro PCB设计88问解析(三十一) 之 Allegro 中 打印(Plot)设置

一个学习信号完整性仿真的layout工程师 在PCB进行投板时&#xff0c;往往会打印一下装备层(Assembly)&#xff0c;给贴片&#xff0c;用于核对器件的信息等。下面简单介绍Allegro中打印(Plot)设置。 1. 在Allegro的菜单下选择File命令&#xff0c;点击Plot Setup&#xff0c;会…

无线振弦采集仪应用于岩土工程安全监测的解决方案

无线振弦采集仪应用于岩土工程安全监测的解决方案 随着现代岩土工程的发展&#xff0c;工程规模越来越大&#xff0c;地质灾害频发&#xff0c;安全监测成为岩土工程的重要组成部分。传统的安全监测方法存在一些局限性&#xff0c;如无法实时监测&#xff0c;监测精度不高等问…

途乐证券-沪指震荡跌0.25%,半导体等板块走弱,地产等板块拉升

19日早盘&#xff0c;沪指窄幅震动下探&#xff0c;深成指、创业板指均走低&#xff1b;两市半日成交约4300亿元&#xff0c;北向资金净卖出超40亿元。 截至午间收盘&#xff0c;沪指跌0.25%报3189.81点&#xff0c;深成指跌0.51%&#xff0c;创业板指跌1%&#xff1b;两市合计…

《2023购物中心运营数字化白皮书》正式发布!|爱分析报告

在国家政策鼓励线下实体经济发展、鼓励消费的大背景下&#xff0c;购物中心的发展潜力巨大。但另一方面&#xff0c;随着行业进入存量时代&#xff0c;竞争愈发激烈&#xff0c;品牌扩张乏力&#xff0c;购物中心招商压力增大。以数字化手段加持的精细化运营&#xff0c;成为购…

侦听器watch

在代码逻辑中监听某个数据的变化&#xff0c;这个时候就需要用侦听器 watch 来完成了&#xff1b; 1.data的watch <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge&q…

备战秋招 | 笔试强训6

目录 一、选择题 二、编程题 三、选择题题解 四、编程题题解 一、选择题 1、十进制变量i的值为100&#xff0c;那么八进制的变量i的值为&#xff08;&#xff09; A. 146 B. 148 C. 144 D. 142 2、执行下面语句后的输出为 int I1; if(I<0)printf("****\n") …

Java框架 Mybatis入门

0目录 Java框架Mybatis 1..框架介绍 2.Mybatis实战 1.框架介绍 补充MVC思想 为什么使用框架&#xff1f; 效率高&#xff0c;成本低 框架是别人写好的&#xff0c;可以直接调用 框架是基于MVC的思想 框架包中含有MVC思想的所有组成模块&#xff1a;控制层&#xff1b;模型…

zabbix 企业级监控(1) 监控自己

重点一 Zabbix简介在企业网络运维过程中&#xff0c;管理员必须随时关注各服务器和网络的运行状况&#xff0c;以便及时发现问题&#xff0c;尽可能减少故障的发生。当网络中的设备&#xff0c;服务器等数量较多时&#xff0c;为了更加方便&#xff0c;快捷的获得监控信息&…

欧姆龙CP系列PLC以太网通讯欧姆龙cp1e怎么用以太网通讯

大家好&#xff0c;今天要和大家分享的是一款在工控领域中非常实用的产品——捷米特JM-ETH-CP转以太网模块。这款模块采用了即插即用的设计&#xff0c;不仅不会占用PLC的通讯口&#xff0c;而且可以通过复用接口让触摸屏与PLC进行通讯。这个设计真的非常巧妙&#xff0c;相信会…

7-Spring cloud之路由网关zuul

7-Spring cloud之路由网关zuul 1. 前言2. 关于zuul2.1 zuul基本原理2.2 为什么要使用zuul 3. 搭建zuul3.1 项目结构3.2 基本配置3.2.1 pom文件3.2.2 yml文件3.3.3 启动类 3.3 测试看效果3.3.1 演示3.3.1 架构图 4. zuul路由访问映射规则4.1 映射服务提供者的服务名4.2 访问加前…

概率论的学习和整理--番外13:一个经典dubo模型的概率计算等

目录 1 经典模型知识科普 1.1 知识来源 1.2 下面是摘取的部分规则 2 这个经典dubo的概率和期望 2.1 网上计算的概率&#xff0c;期望全是负&#xff0c;赌徒悲剧 2.2 为什么会这样呢 3 假设把下注庄家不抽水&#xff0c;获得100%收益而不是95&#xff0c;多少次后可以赢…

桥梁监测需要哪些设备?

随着我国经济的发展&#xff0c;我国桥梁建设也迈上了新的台阶。截至2022年底&#xff0c;我国的公路桥梁总数达到了103.32万座。然而&#xff0c;随着在役桥梁使用时间的增长&#xff0c;承载能力受到荷载、环境以及结构退化等因素的影响&#xff0c;桥梁安全问题日益凸显。桥…

生成式AI管理规则落地 大模型后时代到来

国家网信办等七部门联合颁布的《生成式人工智能服务管理暂行办法》&#xff0c;给中国生成式AI产业树立了发展规范。 这份监管文件的用意并不止于管控&#xff0c;还用大量的笔墨传递出推动产业发展的原则&#xff0c;尤其强调“鼓励生成式人工智能技术在各行业、各领域的创新…

Unity 锚点 Anchors的通俗易懂详解

一、锚点Anchors是什么 当你在Canvas下建子物体的时候&#xff0c;选中子物体就会自带四个△&#xff0c;如下 这个三角也可以是分开的&#xff0c;如下 值得一提的是&#xff0c;这四个三角只能组成一个矩形&#xff0c;或者一个点&#xff0c;例&#xff08;矩形&#xff09…