哈弗曼编码(C++)

2024-04-24 09:48
文章标签 c++ 编码 弗曼

本文主要是介绍哈弗曼编码(C++),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

通过参考网上资料和自己调试,终于编写好了哈弗曼编码
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct node
{int weight;int parent;int lchild;int rchild;
};
struct Nchar
{char n;int weight;char* code;};
class huffman
{int n;string text;node * huffTree;Nchar * nchar,CharMapNode;void select(int n, int &s1, int &s2);//查询权值最小的两项
public:void gettext(char* CHAR);//读取文件内容void savetext(char* CHAR);//将结果保存void creattable();//根据读取文件内容,确定的权值,创建表void CountCharsWeight();//统计读取的文件内容的各字符的权值void display();//显示表,及权值void coding();//编码};
void huffman::gettext(char* CHAR)
{ifstream into(CHAR);if(!into){cerr << "无法打开文件!" <<endl;exit(0);}char a;while(into.get(a)){text+=a;}
}
void huffman::savetext(char* CHAR)
{ofstream out(CHAR);int m=2*n-1;for(int a=1;a<=m;a++){out<<a<<": rchild:"<<huffTree[a].rchild<<"  lchild:"<<huffTree[a].lchild<<"  parent:"<<huffTree[a].parent<<"  weight:"<<huffTree[a].weight<<endl;}out<<"---------------------------------------------"<<endl;for(int h=1;h<=n;h++){out<<nchar[h].n<<"的权值为:"<<nchar[h].weight<<"  编码为:"<<nchar[h].code<<endl;}}
void huffman::select(int n, int &s1, int &s2)
{s1 = s2 = 0;for (int i = 1; i <= n; ++i){if (huffTree[i].parent != 0)continue;if (s1 == 0)s1 = i;else if (s2 == 0){//此处采用的策略,使得整个过程中s1的权值小于s2的权值if (huffTree[i].weight < huffTree[s1].weight){s2 = s1;s1 = i;}elses2 = i;}else{if (huffTree[i].weight < huffTree[s1].weight){s2 = s1;s1 = i;}else if (huffTree[i].weight < huffTree[s2].weight)s2 = i;}}
}
void huffman::creattable()
{huffTree = new node[2*n];for(int m1=1;m1<=n;m1++){huffTree[m1].lchild=0;huffTree[m1].rchild=0;huffTree[m1].parent=0;huffTree[m1].weight=nchar[m1].weight;}for(int k=n+1;k<=2*n-1;k++){huffTree[k].lchild=0;huffTree[k].rchild=0;huffTree[k].parent=0;huffTree[k].weight=0;}int m = 2 * n - 1;for (int i = n + 1; i <= m; ++i)
{int s1,s2;select(i - 1, s1, s2);huffTree[s1].parent = huffTree[s2].parent = i;huffTree[i].lchild = s1;huffTree[i].rchild = s2;huffTree[i].weight = huffTree[s1].weight + huffTree[s2].weight;
}
}void huffman::CountCharsWeight()
{int i = 0;n = 0;nchar = new Nchar[2];nchar[1].n=text[i];nchar[1].weight=1;n++;for(i=1;i<text.size();i++){int j;for (j = 1; j <= n; ++j)	//遍历当前字符表,如果已存在该字符,权值+1{if (text[i] == nchar[j].n){++nchar[j].weight;break;}}if(j>n){++n;Nchar* newchars = new Nchar[n + 1];memcpy(newchars, nchar, n * sizeof(Nchar));delete nchar;nchar = newchars;nchar[n].n = text[i];nchar[n].weight = 1;}}huffman::n=n;}
void huffman::display()
{int m=2*n-1;for(int a=1;a<=m;a++){cout<<a<<": rchild:"<<huffTree[a].rchild<<"  lchild:"<<huffTree[a].lchild<<"  parent:"<<huffTree[a].parent<<"  weight:"<<huffTree[a].weight<<endl;}cout<<"---------------------------------------------"<<endl;for(int h=1;h<=n;h++){cout<<nchar[h].n<<"的权值为:"<<nchar[h].weight<<"  编码为:"<<nchar[h].code<<endl;}cout<<"---------------------------------------------"<<endl;}
void huffman::coding()
{//从叶子到根节点逆向求每个字符的哈弗曼编码char *cd = new char[n];	//分配求编码的工作空间(每个字符编码结果最长n-1再加上'\0')cd[n-1] = '\0';			//编码结束符for(int i = 1; i <= n; ++i)		//逐个字符求哈弗曼编码{int start = n - 1;int c,f;//从叶子到根逆向求编码for (c = i, f = huffTree[i].parent; f != 0; c = f, f = huffTree[f].parent){if (huffTree[f].lchild == c)	//左孩子编码为0cd[--start] = '0';else							//右孩子编码为1cd[--start] = '1';}nchar[i].code = new char[n - start];	//为第i个字符编码分配空间strcpy(nchar[i].code,&cd[start]);}delete cd;
}void main()
{huffman hum;hum.gettext("text.txt");hum.CountCharsWeight();hum.creattable();hum.coding();hum.savetext("SaveText.txt");hum.display();
}

这篇关于哈弗曼编码(C++)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/931416

相关文章

Python使用自带的base64库进行base64编码和解码

《Python使用自带的base64库进行base64编码和解码》在Python中,处理数据的编码和解码是数据传输和存储中非常普遍的需求,其中,Base64是一种常用的编码方案,本文我将详细介绍如何使... 目录引言使用python的base64库进行编码和解码编码函数解码函数Base64编码的应用场景注意

C++ 中的 if-constexpr语法和作用

《C++中的if-constexpr语法和作用》if-constexpr语法是C++17引入的新语法特性,也被称为常量if表达式或静态if(staticif),:本文主要介绍C++中的if-c... 目录1 if-constexpr 语法1.1 基本语法1.2 扩展说明1.2.1 条件表达式1.2.2 fa

C++中::SHCreateDirectoryEx函数使用方法

《C++中::SHCreateDirectoryEx函数使用方法》::SHCreateDirectoryEx用于创建多级目录,类似于mkdir-p命令,本文主要介绍了C++中::SHCreateDir... 目录1. 函数原型与依赖项2. 基本使用示例示例 1:创建单层目录示例 2:创建多级目录3. 关键注

C++从序列容器中删除元素的四种方法

《C++从序列容器中删除元素的四种方法》删除元素的方法在序列容器和关联容器之间是非常不同的,在序列容器中,vector和string是最常用的,但这里也会介绍deque和list以供全面了解,尽管在一... 目录一、简介二、移除给定位置的元素三、移除与某个值相等的元素3.1、序列容器vector、deque

C++常见容器获取头元素的方法大全

《C++常见容器获取头元素的方法大全》在C++编程中,容器是存储和管理数据集合的重要工具,不同的容器提供了不同的接口来访问和操作其中的元素,获取容器的头元素(即第一个元素)是常见的操作之一,本文将详细... 目录一、std::vector二、std::list三、std::deque四、std::forwa

C++字符串提取和分割的多种方法

《C++字符串提取和分割的多种方法》在C++编程中,字符串处理是一个常见的任务,尤其是在需要从字符串中提取特定数据时,本文将详细探讨如何使用C++标准库中的工具来提取和分割字符串,并分析不同方法的适用... 目录1. 字符串提取的基本方法1.1 使用 std::istringstream 和 >> 操作符示

C++原地删除有序数组重复项的N种方法

《C++原地删除有序数组重复项的N种方法》给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度,不要使用额外的数组空间,你必须在原地修改输入数组并在使用O(... 目录一、问题二、问题分析三、算法实现四、问题变体:最多保留两次五、分析和代码实现5.1、问题分析5.

C++ 各种map特点对比分析

《C++各种map特点对比分析》文章比较了C++中不同类型的map(如std::map,std::unordered_map,std::multimap,std::unordered_multima... 目录特点比较C++ 示例代码 ​​​​​​代码解释特点比较1. std::map底层实现:基于红黑

C++中函数模板与类模板的简单使用及区别介绍

《C++中函数模板与类模板的简单使用及区别介绍》这篇文章介绍了C++中的模板机制,包括函数模板和类模板的概念、语法和实际应用,函数模板通过类型参数实现泛型操作,而类模板允许创建可处理多种数据类型的类,... 目录一、函数模板定义语法真实示例二、类模板三、关键区别四、注意事项 ‌在C++中,模板是实现泛型编程

利用Python和C++解析gltf文件的示例详解

《利用Python和C++解析gltf文件的示例详解》gltf,全称是GLTransmissionFormat,是一种开放的3D文件格式,Python和C++是两个非常强大的工具,下面我们就来看看如何... 目录什么是gltf文件选择语言的原因安装必要的库解析gltf文件的步骤1. 读取gltf文件2. 提