首页 > 其他分享 >哈夫曼编码及前缀码的实现

哈夫曼编码及前缀码的实现

时间:2023-11-19 20:00:48浏览次数:30  
标签:parent 编码 前缀 哈夫曼 int i2 weight i1 huffman

哈夫曼编码

我们的任务是选一篇英语文章统计每个字符的概率,并实现哈夫曼前缀编码
所选文章内容:

life is too short to spend time with people who suck the happiness out of you if someone wants you in their life they ll make room for you You shouldnt have to fight for a spot never ever insist yourself to someone who continuously overlooks your worth and remember its not the people that stand by your side when youre at your best but the ones who stand beside you when youre at your worst that are your true friends

程序主要包括统计文章字符数组函数、哈夫曼前缀码的实现
//全部代码
#include<iostream>
#include<fstream>
#include<string>
using namespace std;

struct Node {
	int weight;//权重
	int  parent, lchild, rchild; //游标
	char code;
};

class HuffmanTree {
private:
	Node* huffman;//定义结构体指针
	int num;
	void Select(int n, int &i1, int &i2);
public:
	HuffmanTree(int w[], int n);//构造函数,传入的数组是文章每个字母的权值,n是字母个数
	//	    ~HuffmanTree();
	void Print();//输出函数
	void Encode(int i);//解码函数
	void Codeing();//编码函数
};

//构造函数
HuffmanTree::HuffmanTree(int w[], int n) {
	int i, k, i1, i2;
	huffman = new Node [2 * n - 1];//开辟一个长度为2*n-1的结构体数组
	num = n;
	for ( i = 0; i < 2 * num - 1; i++) {//初始化权值的游标
		huffman[i].parent = -1;
		huffman[i].lchild = -1;
		huffman[i].rchild = -1;
	}
	for ( i = 0; i < num; i++) {//赋初始值
		huffman[i].weight = w[i];
	}
	for (k = num; k < 2 * num - 1; k++) {
		Select(k, i1, i2);//调用select函数,遍历每个权值数据
		huffman[k].weight = huffman[i1].weight + huffman[i2].weight;
		huffman[i1].code = '0';huffman[i2].code = '1';
		huffman[i1].parent = k;huffman[i2].parent = k;
		huffman[k].lchild = i1;huffman[k].rchild = i2;
	}
}

//筛选函数
void HuffmanTree::Select(int n, int &i1, int &i2) {
	int i = 0, temp;
	for (; i < n; i++) {		//遍历每个权值
		if (huffman[i].parent == -1) {
			i1 = i;break;
		}
	}
	for ( i = i + 1; i < n; i++) {
		if (huffman[i].parent == -1) {
			i2 = i;break;
		}
	}
	if (huffman[i1].weight > huffman[i2].weight) {
		//如果发现i1>i2就换掉换
		temp = i1;i1 = i2;i2 = temp;
	}
	for ( i = i + 1; i < n; i++) {
		if (huffman[i].parent == -1) {
			if (huffman[i].weight < huffman[i1].weight) {
				i2 = i1;i1 = i;
			} else if (huffman[i].weight < huffman[i2].weight) {
				i2 = i;
			}
		}
	}
}

//输出函数
void HuffmanTree::Print() {
	int i, k;
	cout << "每个叶子到根结点的路径是:" << endl;
	for ( i = 0; i < num; i++) {
		cout << huffman[i].weight;
		k = huffman[i].parent;
		while (k != -1) {
			cout << "-->" << huffman[k].weight;
			k = huffman[k].parent;
		}
		cout << endl;
	}
}

//解码函数
void HuffmanTree::Encode(int i) {
	if (huffman[i].parent == -1) {
		return;
	} else {
		Encode(huffman[i].parent);
	}
	cout << huffman[i].code;
}

//编码函数
void HuffmanTree::Codeing() {
	for (int i = 0; i < num; i++) {
		if (huffman[i].lchild == -1 && huffman[i].rchild == -1) {
			Encode(i);cout<<"  ";
		}
	}
}

//统计字符频率的函数(外部函数)
void Statistic(string ch, int weight[]) {
	//用来统计字符出现的次数,你也可以认为是权值的集合。i表示对应的元素,sum[i]表示对应元素出现的次数
	int sum[26];
	for (int i = 0; i < 26; i++) {
		sum[i] = 0; //将数组元素置0
	}
	for (int i = 0; i < ch.length(); i++) {
		if ((ch[i] >= 'a') && (ch[i] <= 'z')) {
			sum[ch[i] - 'a']++;
		}
	}
	char a = 'a';
	for (int i = 0; i < 26; i++) {
		cout << a << " : " << sum[i] << "  ";
		a++;
		weight[i] = sum[i];
	}
}

int main() {
	ifstream fin;
	fin.open("document.txt", ios::in);
	if (!fin.is_open()) {
		cout << "无法找到这个文件!";
		return 0;
	}
	string buf;
	cout << "结果:" << endl;
	int weight[26];
	int i = 0;
	while (getline(fin, buf)) {
		Statistic(buf, weight);
	}
	cout<<endl;
	HuffmanTree h(weight, 26);
	cout<<"编码结果为:"<<endl;
	h.Codeing();
	cout<<endl;
	h.Print();	
	return 0;
}
结果:

标签:parent,编码,前缀,哈夫曼,int,i2,weight,i1,huffman
From: https://www.cnblogs.com/zhzbubai/p/17842492.html

相关文章

  • 【4.0】Python中级之字符编码
    【一】文本编辑器与Python解释器原理字符串类型、文本文件的内容都是由字符组成的,但凡涉及到字符的存取,都需要考虑字符编码的问题。【1】数据存放位置所有软件都是运行硬件之上的与运行软件相关的三大核心硬件为cpu、内存、硬盘软件运行前,软件的代码及其相关数据都......
  • 自然语言处理预训练—— 来自Transformers的双向编码器表示(BERT)
    我们已经介绍了几种用于自然语言理解的词嵌入模型。在预训练之后,输出可以被认为是一个矩阵,其中每一行都是一个表示预定义词表中词的向量。事实上,这些词嵌入模型都是与上下文无关的。让我们先来说明这个性质。 从上下文无关到上下文敏感ELMo(EmbeddingsfromLanguageModels)是......
  • requests+编码模块+百度贴吧数据抓取
    1.查看本地发送过去的头文件importrequestshtml=requests.get(url='http://httpbin.org/get').textprint(html)2.编码模块使用  //使用原因:URL不能识别中文编码,中文转换为编码模式)(1)urlencode()方法fromurllibimportparseparams=parse.urlencode({'wd':'赵丽颖'})......
  • 神辅助 Cursor 编辑器,加入 GPT-4 让编码更轻松!-未来:复制粘贴工程师转向提示工程师
    在ChatGPT问世之前,我们的编码方式很多时候都是面向搜索引擎编码,需要不断地进行搜索,然后复制粘贴,俗称复制粘贴工程师。但是,随着ChatGPT的出现,这一切将彻底改变。ChatGPT是一种基于人工智能的自然语言处理模型,可以根据上下文理解人类语言并生成相应的回复。在编码方面,ChatGPT可......
  • 动量编码器
    自监督学习自监督学习属于无监督学习范式的一种,不需要人工标注的类别信息,直接利用数据本身作为监督信息。自监督学习分为自监督生成式学习和自监督对比学习。自监督生成式学习的方法以图片为例,自监督学习可以是将图片的位置信息,旋转角度,以及图片在视频帧中的顺序作为标签。比......
  • 编码与解码
    一,ascii码不支持中文支持英文,数字,字母,符号8位数,一个字节二,gbk国标支持中文,英文,数字,符号英文16位,2个字节中文16位,2个字节三,unicode万国码支持中文,英文,数字,符号英文32位,4个字节中文32位,4个字节四,utf-8长度可变的万国码,最少用8位中文24位,3个字节英文8位’,2个......
  • 基于物理层网络编码的相位同步算法matlab仿真
    1.算法运行效果图预览   2.算法运行软件版本matlab2022a 3.算法理论概述       基于物理层网络编码的相位同步算法是一种利用物理层网络编码技术来实现相位同步的算法。这种算法的原理是将两个或多个相位不同的信号进行叠加,产生一个叠加信号,然后通过分析叠加......
  • DHCPv6 PD(Prefix Delegation)前缀代理
    概念DHCPv6前缀代理DHCPv6PD(PrefixDelegation)是一种前缀分配机制,通过DHCPv6前缀代理机制,下游网络设备不需要再手工指定用户侧链路的IPv6地址前缀,它只需要向上游网络设备提出前缀分配申请,上游网络设备便可以分配合适的地址前缀给下游设备,下游设备把获得的前缀再通过路由通告(RA)......
  • day04 进制和编码
    day04进制和编码课程目标:讲解计算机中一些必备的常识知识,让学员了解一些常见名词背后的含义(重在理解)。课程概要:python代码的运行方式进制计算机中的单位编码1.Python代码运行方式脚本式python3~/PycharmProjects/day03/6.作业题讲解.py交互式python32.进......
  • 机器学习——编码器和解码器架构
    正如我们在 9.5节中所讨论的,机器翻译是序列转换模型的一个核心问题,其输入和输出都是长度可变的序列。为了处理这种类型的输入和输出,我们可以设计一个包含两个主要组件的架构:第一个组件是一个编码器(encoder):它接受一个长度可变的序列作为输入,并将其转换为具有固定形状的编码......