树的企业应用-哈夫曼编码树-有趣的数据压缩算法

树的企业应用-哈夫曼编码树-有趣的数据压缩算法

哈夫曼编码 描述

张三李四家里,但 李四是一个女生,所以张三李四去上海迪尼斯玩 …

亚历山大.张三伊丽莎白.李四家里,但 伊丽莎白.李四是一个女生,所以亚历山大.张三伊丽莎白.李四去美国迪尼斯玩 …

我们发现 一个关键点 有些重复的也不多 无非就高亮的地方 所以简化一下

声明一下 在上方的引言里 凡是出现高亮的 统统替换为 “张三” and “李四”

张三李四家里,但 李四是一个女生,所以张三李四去上海迪尼斯玩 ………

张三李四家里,但 李四是一个女生,所以张三李四去美国迪尼斯玩 ………

哈夫曼编码:把字符出现的次数压缩成只有一个

这就是哈夫曼编码 基本描述

哈夫曼编码树原理

字符串为 **"yyds ndd yygq bbq jjz xdxl jj qq wx dy wb bz ww " **

进行压缩变成如下表格:

字符 该字符出现的次数
‘y’ 5
‘d’ 5
‘b’ 4
‘g’ 1
‘q’ 4
‘z’ 2
‘x’ 3
‘j’ 4
‘w’ 4
’ ’ 13

我们使用文本的方式储存这些 字符和出现的频率(注意:此博主比较懒输入,干脆整成一个文件)

input.txt:

y 5 d 5 g 1 q 4 z 2 x 3 j 4 w 4   13 

在这里插入图片描述

那问题来了 哈夫曼编码树? 这些只是从文件读取到内存里整成了一个顺序表, 而已

我们使用C I/O的函数 来读取 文件 .

回过神来!

能看得出来这些是一体的 所以ndd(你懂的),我们应该定义 全新的数据类型 : Huffman_Code

哈夫曼编码树数据域定义

 struct HuffmanCode{
   
 	char Val;//数据
    int weight;//频率
 }

定义完 先实现读取字符和频率

既然是顺序表 那还得用 统计 input.txt 文件的数据和频率多少个元素


const char* FileName = "input.txt";
const char* OpenMode = "r";
//读取的格式: 数据 空格 权值 空格
const  char* readFormat = "%c %d ";

//统计文件中的数据和频率的个数并且通过参数修改
bool  getSize(int& size) {
   

	FILE* ReadStream = nullptr;

	const	errno_t  openState = fopen_s(&ReadStream, FileName, OpenMode);
	bool ret = openState == 0;

	if (ret) {
   
		int i = 0;

		char ch = getc(ReadStream);
		ret = ch != EOF;
		if (ret) {
   

			ungetc(ch, ReadStream);
			HuffmanCodeValue value{
   };
			int ReadNum = 0;
		    while (!feof(ReadStream)) {
   

				ReadNum = fscanf_s(ReadStream, readFormat, &value.value, sizeof(value.value), &value.weight, sizeof(value.weight));
				++i;
				
			}
			size = i;
		}
		else {
   

			cerr << "错误:" << FileName << "里文件为空" << endl;
		}
	

		fclose(ReadStream);
		ReadStream = nullptr;

	
	}
	else {
   

		char error[1024]{
   };
		strerror_s(error, errno);
		cerr << "错误:" << error << endl;
	}

	return ret;
}

分配好内存 之后 读取文件中的数据


//获取文件 哈夫曼编码 以及编码的权值
void loadValue(HuffmanCodeValue* value, const int &size) {
   

	if (size!=0){
   


		FILE* ReadStream = nullptr;

		const errno_t  openState = fopen_s(&ReadStream, FileName, OpenMode);
		bool ret = openState == 0;

		if (ret) {
   
			
			auto First = 0;
			int ReadNum = 0;
			char read[alignof(HuffmanCodeValue)+ 1];
			
			while (First != size && !feof(ReadStream)) {
   

				ReadNum = fscanf_s(ReadStream, readFormat, &value[First].value, sizeof(value[First].value), &value[First].weight, sizeof(value[First].weight));
			

				++First;
			}

			fclose(ReadStream);
			//free(ReadStream);
			ReadStream = nullptr;
		}

	}
}

读取完毕后 ,是时候 该设计一些数据结构了(也是,最骚脑的时刻)

哈夫曼编码树的定义

//哈夫曼编码树节点
struct HuffmanCodeTreeNode{
	HuffmanCode value;//数据
	HuffmanCodeTreeNode* Parent;//父节点
	HuffmanCodeTreeNode* LeftChild;//左子节点
	HuffmanCodeTreeNode* RightChild;//右子节点
};
//哈夫曼编码树
struct HuffmanCodeTree {
	HuffmanCodeTreeNode* root;//根节点
};

你以为到这里就结束了吗 …

那你就有点小瞧了哈夫曼编码树 还得按照优先级的频率来的

所以 还得吧写好的优先级队列搬出来

#ifndef __PriorityQueue_H__
#define __PriorityQueue_H__
#include"HuffmanTree.h"

using Element = HuffmanCodeTreeNode*;
using  PriorityQueueNode = struct _PriorityQueueNode;

using  PriorityCompare = bool (*)(const int &, const int &);

using PriorityQueueAuxiliary = struct _PriorityQueueAuxiliary;

using  PriorityQueue = struct _PriorityQueue;

struct _PriorityQueueNode {
	int Priority;
	Element value;
	PriorityQueueNode* next;
};

struct  _PriorityQueueAuxiliary {

	PriorityQueueNode* froot;
	PriorityQueueNode* back;
};

struct _PriorityQueue {
	PriorityCompare Compare;
	size_t size;
	PriorityQueueAuxiliary Auxiliary;
};

const size_t MaxSize = 1024;

void initPriorityQueue(PriorityQueue& priorityQueue, PriorityCompare c);
void PushPriorityQueue(PriorityQueue& priorityQueue,const Element& value);
bool fullPriorityQueue(const PriorityQueue& priorityQueue);
bool emptyPriorityQueue(const PriorityQueue& priorityQueue);
Element& PriorityQueueFroot(PriorityQueue& priorityQueue);// 禁止
//删除优先级队列 Element& value 设置到 value 里
void PopPriorityQueue(PriorityQueue& priorityQueue, Element& value);
void setCompare(PriorityQueue& priorityQueue, PriorityCompare Compare);
const size_t& PriorityQueueSize(PriorityQueue& priorityQueue);
void destroyPriorityQueue(PriorityQueue& priorityQueue);

#endif

PriorityQueue.cpp

#include"PriorityQueue.h"
#include<stdexcept>
using namespace std;


using Node = PriorityQueueNode;
const<
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小森程序员

若能帮助到你,小费自愿付费

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值