文件压缩-HuffMan压缩

带你手把手实现Huffman压缩 文件压缩是我们日常所用运最广泛的应用了,但是你是否好奇它是如何实现文件压缩,又如何解压。这篇文章将带你撩开文件压缩的神秘面纱,带你实现一个基于huffman编码最简单的文件压缩项目。看到这里有Huffman编码不要怕,Huffman编码其实很简单。... 阅读详情
什么是HuffMan压缩:
简单来说就是利用Huffman树生成Huffman编码,对文件重复出现的字符进行记录,以减少出现次数。从而达到压缩文件的目的。
为什么HuffMan就能实现文件压缩呢?
数据在硬盘中的存储是有格式的,比如说字符就是char类型的,占了8个比特位,但是实际上有些字符可能根本就用不了8个比特位,因此就造成了空间的浪费。而huffman就是根据字符出现的次数重新建立存储规则,减少这些空间浪费。
什么是HuffMan树?

定义: Huffman树,又称最优二叉树,是加权路径长度最短的二叉树。
带权路径长度 = 节点的权值 * 当前节点距离根节点的路径长度
在这里插入图片描述

如何构建HuffMan树?

在这里插入图片描述

生成HuffMan编码

HuffMan树中左子树路径标记为0,右子树路径标记为1.从根节点到叶子结点的编码就是该字符的Huffman编码。
在这里插入图片描述

HuffMan文件压缩原理:

1.统计待压缩文件中每个字符出现的次数

  • 构建结构体,存放信息:字符,次数,编码
  • 遍历源文件,将每个字符的次数写入对应的结构体信息中

2.将字符出现的次数作为权值构建Huffman树

  • 普通的二叉树只能通过双亲节点找到子节点,但是在获取编码的时候需要通过叶子结点往根节点走,所有构建二叉树时,要有子节点指向双亲节点

3.通过Huffman树获取每个字符所对应的编码

  • 通过叶子结点找根节点的编码是逆序的,所以要使用reverse

4.向压缩文件中写入信息

  • 压缩文件中只保存压缩的文件内容是不够的,还要有一些记录源文件内容的信息
  • 第一行:存放源文件的后缀,因为在解压缩文件的时候需要后缀
  • 第二行:存放源文件字符,次数 的总行数
  • 第三行:存放字符和字符出现的次数–为了解压缩重建Huffman树
  • 剩余内容是压缩编码
    例如:源文件名为“1.txt”,存放“ABBBCCCCCDDDDDDD”
    在压缩文件中的模型为:
    在这里插入图片描述
解压缩:

1.获取后缀
2.获取字符以及对应的次数
3.重建Huffman树
4.解压压缩数据

  • 从压缩文件中读取一个字节ch
  • 从根节点开始,按照ch的8个比特位信息(代表字符的编码)从高到低遍历Huffman树:
    a.该比特位是0,取当前节点的左孩子,否则取右孩子
    b.一直遍历,直到遍历到叶子节点位置,该字符就被解析成功,讲解压出来的字符写入文件
    c.如果在遍历Huffman过程中,8个比特位已经比较完毕还没有到达叶子节点,就从第四步开始执行
    d.重复以上过程,直到所有的数据解析完毕
问题:

1.压缩汉字时候程序会崩溃,但是压缩字母程序就能正常运行?

  • 原因:创建存放信息的数据是char 类型的,类型大小是1字节(0~255),但是汉字都是占两个字节的,对应的char类型就会因为超过255而导致数组的下边变成负数,数组下边越界访问导致程序崩溃。
  • 解决方法:将存放信息的数据类型改成unsigned char 类型

2.解压大文件,只能解压缩一部分内容?

  • 原因:一般情况下,文件指针碰到EOF就表示到文件结尾了,因为EOF是 -1,也就是FF,所以只解压了一部分(解压到第一个FF就停止了)。
  • 解决方法:采用 feof()函数,多加一个判断即可,feof()函数就是判断文件末尾,而不仅仅是碰见EOF停止。

3.为什么压缩照片的时候会失败?

  • 原因:是因为 ‘\0’ 的问题,因为如果刚开始把(字节,次数)先写入 buf 中,再由 buf 通过 fwrite 函数写入文件中,一定会出现问题(可能出现 0 字节)。因为 fwrite 的第一个参数要求C格式的字符串,把 buf 转化为C格式的字符串,如果遇见 ‘\0’,就会停止,所以就会崩溃。
  • 解决方法:不要将字节写入 buf 中,而是通过 fputc 直接把字节写入文件中,然后再写入 buf 中,再将buf写入文件即可。

文件压缩的图解过程:

在这里插入图片描述


源码:
main.c

#include "HuffmanTree.hpp"
#include "FileCompressHuffman.h"

int main()
{
	//TestHuffman();

	FileCompressHuffmanM test;
	//test.CompressFile("文件压缩(原文件).png");

	test.UnCompressFile("文件压缩.hzp");
	return 0;
}



huffmanTree.hpp

#pragma once
#include<iostream>
using namespace std;
#include<vector>
#include<queue>


template<class W>
struct HuffmanTreeNode   //定义哈弗曼树节点的类型
{
	HuffmanTreeNode(const W& weight)
		:_pLeft(nullptr)
		, _pRight(nullptr)
		, _pParent(nullptr)
		, _weight(weight)
	{}

	HuffmanTreeNode<W>* _pLeft;
	HuffmanTreeNode<W>* _pRight;
	//用孩子双亲形式表示二叉树,方便从叶子结点找到根节点,从而对字符进行编码
	HuffmanTreeNode<W>* _pParent;

	W _weight;   //节点权值
};

template<class W>
struct Compare //用仿函数比较,变小堆
{
	typedef HuffmanTreeNode<W>* PNode;
	bool operator()(const PNode pLeft, const PNode pRight)
	{
		return pLeft->_weight > pRight->_weight;
	}
};


template<class W>
class HuffmanTree
{
	typedef HuffmanTreeNode<W> Node;
	typedef Node* PNode;
public:
	HuffmanTree()//构造函数,初始状态下为空树
		: _pRoot(nullptr)
	{}

	void CreatHuffmanTree(const std::vector<W>& v, const W& invalid)  //根据权值创建树,模板引用   vector在标准的命名空间中定义的
	{
 		if (v.empty())   //v是存放权值的数组
			return;
		//用所给的权值创建二叉树森林
		//std::priority_queue<PNode> q;    使用仿函数实现 小堆  比较器
		std::priority_queue<PNode,std::vector<PNode>,Compare<W>> q;//优先级队列 保存树,把地址放进去就好了,,但是默认是大堆,而我们需要的是小堆

		for (size_t i = 0; i < v.size(); ++i)
		{
			if (v[i] != invalid)  //过滤出现0次的字符,通过创建哈弗曼树多加上一个参数 来实现
			q.push(new Node(v[i]));  //用权值创建节点
		}
		while (q.size() > 1)  //当树不止一个时,把作为左右孩子
		{
			PNode pLeft = q.top();
			q.pop();

			PNode pRight = q.top();
			q.pop();

			PNode pParent = new Node(pLeft->_weight + pRight->_weight);
			
			pParent->_pLeft = pLeft;
			pLeft->_pParent = pParent;

			pParent->_pRight = pRight;
			pRight->_pParent = pParent;
			q.push(pParent);   //把两个子树生成的树放回队列中
		}
		_pRoot = q.top();   //哈夫曼树创建成功
	}

	PNode GetRoot()
	{
		return _pRoot;
	}

	~HuffmanTree()
	{
		_Destroy(_pRoot);   //销毁 哈夫曼树
	}

private:
	void _Destroy(PNode& pRoot)   //后序遍历进行销毁二叉树
	{
		if (pRoot)
		{
			_Destroy(pRoot->_pLeft);
			_Destroy(pRoot->_pRight);
			delete pRoot;
			pRoot = nullptr;
		}
	}

private:
	PNode _pRoot;
};


//void TestHuffman()
//{
//	std::vector<int> v{ 3,1,7,5 };
//	HuffmanTree<int> ht;
//	ht.CreatHuffmanTree(v);
//}

FileCompressHuffman.h

#pragma once
#include<string>
#include<iostream>
#include<vector>
#include "HuffmanTree.hpp"
using namespace std;

typedef unsigned char UCH;

//哈夫曼树中的字符信息,包括字符代表的字母,次数,编码
struct CharInfo
{
	//用构造函数初始化哈夫曼树中的字符
	CharInfo(size_t charCount = 0)
		: _charCount(charCount)
	{}

	//权值在结构体中,而结构体不能直接相加,所以要重载+
	CharInfo operator+(const CharInfo& info)  //字符出现的次数
	{
		return CharInfo(_charCount + info._charCount);
	}

	bool operator>(const CharInfo& info)
	{
		return _charCount > info._charCount;
	}

	bool operator!=(const CharInfo& info)const
	{
		return _charCount != info._charCount;
	}
	bool operator==(const CharInfo& info)const
	{
		return _charCount == info._charCount;
	}

	UCH _ch;
	size_t _charCount;
	std::string _strCode;
};

class FileCompressHuffmanM
{
public:
	FileCompressHuffmanM();
	void CompressFile(const std::string& strFilePath);  //const 保证原文件不会被修改
	void UnCompressFile(const std::string& strFilePath);//不加命名空间会如何?
	void WriteHead(FILE* fOut, const std::string& strFilePath);//头部信息:用来保存压缩文件的信息,包括后缀,字符出现的次数

private:
	void GetHuffmanCode(HuffmanTreeNode<CharInfo>* pRoot);
	void GetLine(FILE* fIn, std::string& strContent);
	std::vector<CharInfo> _charInfo;    //把编码保存在数组中,这个数组是个结构体类型的,字符信息

};

FileCompressHuffmanM.cpp

#pragma once
#include "FileCompressHuffman.h"
#include"HuffmanTree.hpp"
#include <iostream>
#include <assert.h>
using namespace std;

FileCompressHuffmanM::FileCompressHuffmanM() 
{
	_charInfo.resize(256);
	for (size_t i = 0; i < 256; ++i)
	{
		_charInfo[i]._ch = i;  //i是ch 的ASCII码
	}
}


void FileCompressHuffmanM::CompressFile(const std::string& strFilePath)
	{	 
        string MiddleName = strFilePath.substr(0, strFilePath.find('.'));// MiddleName是生成的压缩文件的名称
		//1.获取原文件中每个字符出现的次数
		FILE* fIn = fopen(strFilePath.c_str(), "rb");  //string 类 转换成char*类型
		if (fIn == nullptr)
		{
			cout << "文件打开失败" << endl;
			return;
		}

		UCH *pReadBuff = new UCH[1024];   //每次读取1024字节,即1M
		//long long CharCount[256] = { 0 };   //符号有可能出现很多次,所以出现次数用long long  类型表示
		
		//vector<CharInfo> charInfo(256);
		//初始化_ch

		while (1)
		{
			size_t rdSize = fread(pReadBuff, 1, 1024, fIn);//返回读到的元素个数
			if (0 == rdSize)
				break;
			for (size_t i = 0; i < rdSize; ++i)
			{
				//CharCount[pReadBuff[i]]++; //pReadBuff[i]表示第i个字节读到的内容,对应的ascii码作为数组CharCount的下标
				_charInfo[pReadBuff[i]]._charCount++;
			}
		}
		//2.以每个字符出现的次数作为权值构建哈夫曼树
		HuffmanTree<CharInfo> ht;   //类名 类型 实例化对象
		ht.CreatHuffmanTree(_charInfo,CharInfo(0));

		//3.根据哈弗曼树获取每个字符的编码
		GetHuffmanCode(ht.GetRoot());

		//4.根据每个字符的编码重新改写原文件
		//先打开一个文件,写入压缩信息
		MiddleName += ".hzp";
	
		FILE* fOut = fopen(MiddleName.c_str(), "wb");
		assert(fOut);

		WriteHead(fOut, strFilePath);
		UCH ch = 0;
		char bitCount = 0;
		fseek(fIn, 0, SEEK_SET);

		while (true)
		{
			size_t rdSize = fread(pReadBuff, 1, 1024, fIn);  //把buff中的编码写入压缩文件
			if (0 == rdSize)
				break;

			for (size_t i = 0; i < rdSize; ++i)
			{
				string& strCode = _charInfo[pReadBuff[i]]._strCode;
				// ch: 0000 0000
				// A:100
				// B:101
				for (size_t j = 0; j < strCode.size(); ++j)  //j小于  对应的字符的字符编码的长度
				{
					ch <<=1;
					if (strCode[j] == '1')   //ch初始值是0, ch代表一个字节,不是代表一个比特位,把这八个比特位填满就可以以往压缩文件中写入字节了
						ch |= 1;
					bitCount++;
					if (8 == bitCount)   //每满一个字节,就往压缩文件中写入一个字节
					{
						fputc(ch, fOut);
						bitCount = 0;
					}
				}
			}
		}
		//如果8个bit没有写满,还要把剩余的内容写入压缩文件
		if (bitCount >0 && bitCount < 8)   //大于0的原因是  ,如果8个比特位恰好写满,在上一步中会置0
		{
			ch <<= 8 - bitCount;
			fputc(ch , fOut);
		}

		delete[] pReadBuff;
		fclose(fIn);
		fclose(fOut);
 	}

void FileCompressHuffmanM::UnCompressFile(const std::string& strFilePath)
{
	//获得解压缩文件的名称
	string ResultName = strFilePath.substr(0,strFilePath.find('.'));

	//检测压缩文件的后缀格式
	string strPostFix = strFilePath.substr(strFilePath.rfind('.'));  //有两个参数,第二个默认结尾
	if (".hzp" != strPostFix )
	{
		cout << "压缩文件的格式有问题" << endl;
		return;
	}

	//获取解压缩的信息
	FILE* fIn = fopen(strFilePath.c_str(), "rb");     //fIn 是指向压缩信息 hzp文件   的指针
	if (fIn == nullptr)
	{
		cout << "压缩文件打开失败" << endl;
		return;
	}

	//获取原文件的后缀----读完压缩信息的第一行就行了,第一行保存的就是后缀
	strPostFix = "";
	GetLine(fIn, strPostFix);

	//获取总行数
	string strContent;
    GetLine(fIn, strContent);  //获取在遇到\n前的第一个内容,即行数,此时fIn 指向第一个\n
	size_t lineCount = atoi(strContent.c_str());

	//字符信息
	for (size_t i = 0; i < lineCount; ++i)
	{
		strContent = "";
		GetLine(fIn, strContent);  ////??????     fIn此时不是指向的是\n么?
		if (strContent.empty())   //读取到换行符,如果不处理会直接退出,没有读取到后面的压缩内容
		{
			strContent += '\n';
			GetLine(fIn, strContent);
		}
		_charInfo[(UCH)strContent[0]]._charCount = atoi(strContent.c_str()+2); //获取到次数 获取的字符串是 A,1 字符A对应的是获取的字符串的下标为0 的元素 占据了两个字节,要偏移过去
	}              //strCont 中保存的是字符信息  如果是汉字  也有可能出现负数的情况,所以强转成无符号类型

	//还原哈夫曼树
	HuffmanTree<CharInfo> ht;
	ht.CreatHuffmanTree(_charInfo, CharInfo(0));

	//解压缩
	//string  strUNComFile = NameOfCompressFile;
	string strUNComFile = ResultName;

	strUNComFile += strPostFix;  //名字+后缀
	FILE* fOut = fopen(strUNComFile.c_str(), "wb");
	assert(fOut);

	char* pReadBuff = new char[1024];
	HuffmanTreeNode<CharInfo>* pCur = ht.GetRoot();
	char pos = 7;
	size_t SizeOfFile = pCur->_weight._charCount;


	while (true)
	{
		size_t  rdSize = fread(pReadBuff, 1, 1024, fIn); //从fIn文件中读取
		if (0 == rdSize)
		{
			break;
		}
		for (size_t i = 0; i < rdSize; ++i)
		{
			pos = 7;
			for (size_t j = 0; j < 8; ++j)  //处理当前的一个字节
			{
				//if ((pReadBuff[i] & (1 << pos)) == 1)//1朝右走
				if (pReadBuff[i] & (1 << pos))//1朝右走
					pCur = pCur->_pRight;
				else
					pCur = pCur->_pLeft;  //0朝左走
				if (nullptr == pCur->_pLeft && nullptr == pCur->_pRight)
				{
					fputc(pCur->_weight._ch, fOut);  //把这个字符写到fOut文件中
					pCur = ht.GetRoot();
					SizeOfFile--;
					if (0 == SizeOfFile)
					{
						break;
					}

				}
				pos--;
			}
		}
	}
	delete[] pReadBuff;
	fclose(fIn);
	fclose(fOut);
}

void FileCompressHuffmanM::GetHuffmanCode(HuffmanTreeNode<CharInfo>* pRoot)
{
	if (pRoot == nullptr)
	{
		return;
	}
	GetHuffmanCode(pRoot->_pLeft);
	GetHuffmanCode(pRoot->_pRight);
	if ((pRoot->_pLeft == nullptr) && (pRoot->_pRight == nullptr))
	{
		//找到叶子结点 ,保存叶子节点,并追寻双亲节点
		HuffmanTreeNode<CharInfo>* pCur = pRoot;  //以字符信息作为模板类型,pCur类型是个结构体
		HuffmanTreeNode<CharInfo>* pParent = pCur->_pParent;

		string& strCode = _charInfo[pCur->_weight._ch]._strCode; //?????数组是结构体类型,把编码保存在结构体的_strCode中
		while (pParent)            //以字符的ASCII作为数组的下标:   [叶子结点 中的权值 中的字符]
		{
			if (pCur == pParent->_pLeft)
			{
				strCode += '0';
			}
			else 
			{
				strCode += '1';
			}
			pCur = pParent;
			pParent = pCur->_pParent;
		}
		reverse(strCode.begin(), strCode.end());
	}
}

void FileCompressHuffmanM::WriteHead(FILE* fOut, const std::string& strFilePath)  //写入解压缩需要的信息
{
	string strHeadInfo;
	strHeadInfo = strFilePath.substr(strFilePath.rfind('.'));
	strHeadInfo += '\n';

	string strCharInfo;
	char szCount[32];
	size_t lineCount = 0;
	for (size_t i = 0; i < 256; ++i)
	{
		if (_charInfo[i]._charCount)
		{
			strCharInfo += _charInfo[i]._ch;   //把字符  和  次数放入  头信息中
			strCharInfo += ',';
			_itoa(_charInfo[i]._charCount, szCount, 10);
			strCharInfo += szCount;
			strCharInfo += '\n';
			lineCount++;
		}
	}
	_itoa(lineCount, szCount, 10);     //整型数据要转换成字符串
	strHeadInfo += szCount;
	strHeadInfo += '\n';

	strHeadInfo += strCharInfo;
	fwrite(strHeadInfo.c_str(), 1, strHeadInfo.size(), fOut);
}

void FileCompressHuffmanM::GetLine(FILE* fIn, std::string& strContent)
{
	while (!feof(fIn)) //指针没有在文件末尾,就读取一行
	{
		UCH ch = fgetc(fIn);
		if ('\n' == ch)
		{
			return;
		}
		strContent += ch;
	}
}

基于Huffman树的文件压缩原理及C语言实现(二) 在上文基于Huffman树的文件压缩原理及C语言实现(一)中已经介绍并实现了如何建立Huffman树,得到Huffman编码,这篇我们将会接着说。如何通过Huffman树,实现文件压缩。实现思路任何文件都可以看作是由字节组成的字节块,将字节看作基本编码单元,一个文件就可以看作是由字节组成的信息串。对文件中各字节的出现频率进行统计,并以出现频率作为每个字节块的权值,就可以用字节为叶结点构造哈夫曼树,进 阅读详情

相关推荐

Huffman编码文件压缩

而Huffman编码属于可变长编码,本实验中其依据文本中字符的频率进行编码,频率高的字符的编码长度短(小于8位),而频率低的字符的编码长度长(可能多于8位),如在本实验中,字符’ ’(空格)的出现频率最高(出现65次),其Huffman编码为111(占3位,远小于一个字节的8位),其它出现频率较高的字符,如字符’e’的Huffman编码为011、字符’o’的Huffman编码为111;3. 在生成Huffman树前,初始在对字符频率权重进行(由小至大)排序时,频率相同的字符ASCII编码值小的在前;

Insomniacs_01的博客 1013

文件压缩---huffman算法

万年历online项目链接点击这里本篇文章主要包含4个方面: 1.哈夫曼算法实现压缩的原理 2.具体压缩及解压过程思路阐述 3.项目中遇到的问题 4.项目扩展一、原理简述: huffman算法实现文件压缩的主要原理是通过huffman编码来重新表示字符,使得出现频率高的字符编码短,出现少的字符编码长。当用编码表示原文件时,总体的bit位时相对减少的。但当大部分字符出现的频率都差不多

Fly_bit的博客 1434

C++基于Huffman编码实现文件压缩和解压

实验要求 实验目的 利用Huffman编码实现文件的压缩和解压 实验要求 通过键盘输入原文件路径,对原文件进行压缩操作 通过键盘输压缩文件路径,对压缩文件进行解压操作 程序思路 压缩文件过程 读入一个文本文件,计算其中每一个字符出现的次数。 根据步骤1得到的数据,生成哈夫曼编码树,并得到每种出现字符的具体编码。 将哈夫曼树存储在树信息文件中。 要求使用哈夫曼树的顺序表示法存储树的结构(不存储...

雩停 5343

哈夫曼编码&文件压缩和解压

赫夫曼编码也翻译为 哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式, 属于一种程序算法赫夫曼编码是赫哈夫曼树在电讯通信中的经典的应用之一。赫夫曼编码广泛地用于数据文件压缩。其压缩率通常在20%~90%之间赫夫曼码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,称之为最佳编码。

m0_56280646的博客 5633

Huffman编码之文件的解/压缩

史上最具人性化的文件压缩详述,基于Huffman算法的文件压缩项目,还在为找练习项目而苦恼?还在为Huffman算法困惑?还在为文件压缩一头雾水?来吧,,,一起学习,共同进步.....

Xiao__Tian__的博客 9001

Huffman编码实现压缩、解压文件

Huffman编码:根据词频构建Huffman树,实现对文本的前缀编码。 1、统计文本中每个字符出现的次数,放入优先队列中,构建一棵空的二叉树; 2、取出频率最小的两个字符a、b,字符a、b的频率分别作为此二叉树的左右结点,左结点的编号为1,右结点的编号为0,其频率之和(fa + fb)作为该二叉树的父亲节点,放入优先队列,并将fa  、fb 从优先队列中除去; 3、重复第二步操作,直至

Christine的专栏 4898

huffman压缩

文件压缩是在不丢失有用信息的前提下,缩减数据量以减少存储空间,提高传输、存储火绒处理效率,同时可以对数据加密保护(加密算法),增强数据在传输过程中的安全性有损压缩,可能丢失一些信息,不能还原到与源文件一样的,适合图片压缩,压缩率会更好无损压缩,压缩后的压缩文件可以被还原成与源文件完全相同的格式。

m0_73284013的博客 1462

Huffman编码文件压缩 - Huffman树的建立与编码

【问题描述】 编写一程序采用Huffman编码对一个正文文件进行压缩。具体压缩方法如下: 1.    对正文文件中字符(换行字符'\'除外,不统计)按出现次数(即频率)进行统计 2.    依据字符频率生成相应的Huffman树(未出现的字符不生成) 3.    依据Huffman树生成相应字符的Huffman编码 4.    依据字符Huffman编码压缩文件(即按照Huffman编码

Jason ZHANG的博客 5584

Huffman赫夫曼编码压缩文本文件

哈夫曼编码压缩

qq_45839537的博客 839

Huffman树实现文件的压缩与解压缩

Huffman树的概念 Huffman树是由n个带权叶子节点构成的所有二叉树中带权路径长度最短的二叉树。 节点的带权路径长度 树根到某一节点的路径长度与该节点的权的乘积。 树的带权路径长度 树的带权路径长度为树中从根节点到所有叶子节点的各个带权路径长度之和。 Huffman树的构造步骤: 初始化:将给定的节点都看作根节点,构成森林。 找最小树:在森林中选出两...

苍老的小孩的博客 2938

Huffman的应用之文件压缩与解压缩

文件压缩与解压缩>      最近这段时间一直在学习树的这种数据结构,也接触到了Huffman树以及了解了什仫是Huffman编码,而我们常用的zip压缩也是利用的Huffman编码的特性,那仫是不是可以自己实现一个文件压缩呢?当然可以了.在文件压缩中我实现了Huffman树和建堆Heap的代码,下面开始介绍思路...      1).统计>读取一个文件统计这个文件中字符出现的次数.

微风 4775

基于Huffman算法的文件压缩项目

Huffman算法,文件压缩

qq_55958734的博客 946

【c++】Huffman实现文件压缩

1.需求分析 利用小堆,huffman编码,文件流操作,二进制文件的读写实现对普通文件的压缩和解压过程。 2.能力要求 A.熟悉对文件的读写操作。 B.熟悉小堆的原理。 C.熟悉HuffmanTree的实现原理、 D.会编码的获取。 E.对编码信息处理和存储。 F.最重要一点,要理解压缩和解压缩的过程。 3.模块介绍。 A设计的存储结构。. B.压缩过

azrael___的博客 2455

基于Huffman树的文件压缩

基于Huffman树的文件压缩一、开发环境二、项目原理1. 文件在计算机是如何存储的?2. Huffman算法原理三、项目流程1. 文件压缩01 统计文件中字节出现的频次信息02 根据统计结果构建Huffman树03 通过Huffman树来获取每个字节对应的编码04 对待压缩文件进行改写2. 文件解压缩01 从压缩文件头部获取解压缩所需的信息02 根据获取的信息重新构建Huffman树03 根据huffman树来获取每个字节对应的编码04 将压缩文件中的压缩编码进行转译四、项目测试五、项目中遇到的问题 一、

RONIN_WZ的博客 1135

让 AI 变聪明的 20 条指令:如何让大模型回答得更精准、更专业、更实事求是

让 AI 变聪明,本质上不是写几句神奇咒语,而是把你的任务表达得更清楚,把事实标准设得更严格,把输出格式规定得更明确,把不确定性管理得更认真,把历史对话利用得更充分。大模型的强项是语言生成、信息组织、模式归纳和方案扩展;弱项是事实核验、实时更新、责任判断和对模糊意图的准确猜测。好的指令,就是在用人的判断弥补模型的弱点,让模型把强项发挥在正确的地方。

Sumarua的博客 1468

C++语言程序设计教程第4版杨进才沈显君课后习题答案解析

为了更好地学习这门课程,我尝试在网上寻找一些学习资料和参考书籍,但效果并不是很理想。因此,我希望能有一些学长学姐或者是有经验的程序员能够分享一些学习经验和方法,让我更好地掌握这门课程。学习过程中,我发现这本书的内容非常丰富,讲解也非常详细,对于像我这样编程基础薄弱的学生来说,是一本非常实用的教材。同时,我也希望有经验的程序员能够推荐一些适合初学者的C++语言学习资料和工具,以便我能更好地学习和掌握这门课程。总之,希望能得到大家的帮助和支持,让我更好地学习和掌握C++语言程序设计。主 编: 杨进才,沈显君。

weixin_58833001的博客 1331

Python的Huffman编码文件压缩实现

Python的Huffman编码文件压缩实现 一、背景介绍: Huffman编码是一种无损编码方式,采用Huffman树实现,具体可以见百度百科。 代码参考博客https://blog.youkuaiyun.com/EggWave/article/details/78697965。本篇将Huffman编码文件压缩脱离django框架,独立实现。 二、注意事项: 如果直接将Huffman编码写入文件,一股脑儿...

qq_37645194的博客 2358

机器人路径规划:基于冠豪猪优化算法(Crested Porcupine Optimizer,CPO)的机器人路径规划(提供MATLAB代码)

移动机器人(Mobile robot,MR)的路径规划是 移动机器人研究的重要分支之,是对其进行控制的基础。根据环境信息的已知程度不同,路径规划分为基于环境信息已知的全局路径规划和基于环境信息未知或局部已知的局部路径规划。随着科技的快速发展以及机器人的大量应用,人们对机器人的要求也越来越高,尤其表现在对机器人的智能化方面的要求,而机器人自主路径规划是实现机器人智能化的重要步骤,路径规划是指规划机器人从起点位置出发,无碰撞、安全到达指定目标位置的最优路径。

IT猿手 1365

基于huffman树的文件压缩项目以及相关测试

项目采用Huffman编码的方式进行文件压缩与解压缩。主要原理是通过Huffman编码来表示字符,出现次数多的编码短,出现次数少的编码长,这样整体而言,所需要的bit位是减少的,就实现了文件压缩功能。读取文件中的字符出现次数,构建Huffman树,然后解析这个字符的每一位,遇到一个叶子结点,就代表还原了一个字符,这时就将这个字符写到解压缩文件里。注意当大部分字符出现的频率都差不多时,Huffman压缩的效率比较低。

m0_71808911的博客 1435

华为AR6140E/S5735设备密码策略配置全攻略:从复杂度到锁定机制

本文详细介绍了华为AR6140E/S5735设备的密码策略配置方法,涵盖密码复杂度、时效性和防护性三大核心维度。通过具体的CLI命令示例,指导管理员如何设置密码长度、字符组合、有效期及登录失败锁定等安全机制,为企业网络提供全面的用户名密码防护策略。

weixin_30836759的博客 530

Visual Studio 命令提示符工具区别与使用场景

Visual Studio会提供一系列命令提示符工具,这些工具应用在哪些场景呢?本文进行了相关介绍。

cicada15的博客 3490

用Huffman树实现文件压缩与解压

用Huffman树实现文件的压缩与解压 我们先来了解一下什么是Huffman树? 我们平常所使用的Zip等压缩工具都是借助Huffman树实现的,Huffman是一种特殊的二叉树,它是一种加权路径最短的二叉树, 因此也称为最优二叉树。 (下面用一幅图来说明) 它们的带权路径长度分别为:图1: WPL=3*2+4*2+2*2+10*2=48 图2: WPL=3*3+2*3+4*

CC_clear的博客 4083

下采样优化实战:用ADown显著提升YOLOv11的多尺度特征保持能力

ADown 以“可编程梯度信息+多分支特征融合”打破了传统下采样的性能壁垒,为 YOLOv11 带来了多尺度特征的精准传递能力。从原理到代码集成,本教程已为你铺就了一条“小目标检测精度跃升”的实战路径。现在就动手尝试吧——当你看到模型对极小目标也能精准识别,且特征图细节完整时,你会明白这份技术探索的价值。我很乐意在你实践过程中帮你解决任何问题,让我们一起推动目标检测在下采样领域的边界。

FJN110的博客 421

文件压缩项目(基于Huffman编码)

基于Huffman编码的文件压缩项目

keykilocode的博客 1107

Android 车联网——CarAudioService介绍(六)

CarAudioService 是 Android Automotive OS 中的一个重要组件,用于管理车辆中的音频功能。它是 Android Auto 的一部分,负责处理车辆音频的播放、控制和路由。CarAudioService 使用标准的 Android 组件架构,基于 Binder 通信机制,提供了一组 API,用于管理车辆音频。它包括以下主要功能:音频路由管理:CarAudioService 可以让开发者控制音频的路由,即将音频发送到不同的输出设备,例如车辆的扬声器、耳机等。

小旭的专栏 3199

Python爬虫实战:美团外卖商家数据抓取与分析

随着互联网技术的快速发展,外卖平台已成为人们日常生活中不可或缺的一部分。本文基于Python爬虫技术,使用最新的异步爬虫框架和反爬虫绕过技术,实现了对美团外卖平台商家信息与评分数据的自动化抓取。通过对抓取数据的清洗、存储和分析,为餐饮行业市场研究和商业决策提供数据支持。本文详细介绍了爬虫的设计思路、技术实现方案、数据处理方法以及可视化分析结果,为相关领域的研究者和开发者提供参考。关键词:Python爬虫;美团外卖;数据抓取;数据分析;异步爬虫。

2201_76125261的博客 1821
上一篇: Windows下dos中 copy命令的实现
下一篇: static的作用(5点)
Name_seven
博客等级 码龄9年 12粉丝 40原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值