成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

c++實(shí)現(xiàn)基于哈夫曼編碼的文本(中英混合)壓縮和解壓縮-創(chuàng)新互聯(lián)

目錄

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對這個(gè)行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長期合作伙伴,公司提供的服務(wù)項(xiàng)目有:空間域名、虛擬空間、營銷軟件、網(wǎng)站建設(shè)、沾益網(wǎng)站維護(hù)、網(wǎng)站推廣。

一、什么是哈夫曼編碼?

二、utf-8編碼

三、壓縮流程

1.哈夫曼節(jié)點(diǎn)及漢字判斷

2.獲取字符權(quán)重

3.根據(jù)權(quán)重構(gòu)造哈夫曼樹

4.根據(jù)哈夫曼樹構(gòu)造譯碼表

5.壓縮

四、解壓縮

五、效果展示


一、什么是哈夫曼編碼?

哈夫曼編碼,又稱為哈夫曼編碼(Huffman Coding)是一種可變長編碼( VLC, variable length coding))方式,該方法完全依據(jù)字符出現(xiàn)概率來構(gòu)造異字頭的平均長度最短的碼字,有時(shí)稱之為最佳編碼。

二、utf-8編碼

UTF-8是Unicode的實(shí)現(xiàn)方式之一 并不是唯一 也不等同于Unicode。除了UTF-8 還有UTF-16和UTF-32 只是很少被使用。

UTF-8的特點(diǎn)是對不同范圍的字符使用不同長度的編碼 它可以使用1~4個(gè)字節(jié)表示一個(gè)符號 根據(jù)不同的符號而變化字節(jié)長度。

其編碼規(guī)則很簡單對于單字節(jié)的符號 ,字節(jié)的第一位設(shè)為0 ,后面7位為這個(gè)符號的Unicode碼。因此對于英語字母 UTF-8編碼和ASCII碼是相同的。對于n字節(jié)的符號,其第一個(gè)字節(jié)的前n位都設(shè)為1 第n+1位設(shè)為0 后面字節(jié)的前兩位一律設(shè)為10 剩下的沒有提及的二進(jìn)制位 全部為這個(gè)符號的Unicode碼。

三、壓縮流程 1.哈夫曼節(jié)點(diǎn)及漢字判斷

在utf-8中一個(gè)英文字符占一個(gè)字節(jié),用一個(gè)char表示足矣,但對中文而言,漢字占了三個(gè)字節(jié),所以在這里我采用c++string類來統(tǒng)一表示中英文。

typedef struct huffmannode {
	std::string ch;
	int weight = 0;
	int father = 0;
	int lc = 0, rc = 0;
}huffmanNode;

在讀取文件之前我們要先判斷所讀取的字符是漢字還是英文,由上面的utf-8編碼規(guī)則我們可以知道漢字的第一個(gè)字節(jié)的編碼一定是 1110 xxxx 而英文字符的編碼一定是 0xxx xxxx,所以我們只要判斷字節(jié)的第一位是不是1就行。

bool judgeEng(unsigned char c)
{
	if (!(c & 0x80))
		return true;
	return false;
}

2.獲取字符權(quán)重

在判斷一個(gè)字符是否為漢字后,如果是漢字,就接著再讀兩個(gè)字節(jié),這三個(gè)連著的字節(jié)就是一個(gè)漢字。按此方法將文本遍歷到結(jié)尾,統(tǒng)計(jì)出每個(gè)字符的出現(xiàn)次數(shù)。(為方便,在這里我用了map)

void getWeightMap(ifstream& fin, const char* fileName, map& _weightMap)
{
	fin.open(fileName, std::ios::in);
	unsigned char c;
	std::string s;
	while (fin.peek()!=EOF)
	{
		c = fin.get();
		s = "";
		if (judgeEng(c))
			s += c;
		else
		{
			s += c;
			c = fin.get();
			s += c;
			c = fin.get();
			s += c;
		}
		_weightMap[s]++;
	}
	fin.close();
}
3.根據(jù)權(quán)重構(gòu)造哈夫曼樹
void getHuffmanTree(map& _weightMap, vector& _huffmanTree)
{
	int n = _weightMap.size();
	for (auto it : _weightMap) {
		huffmannode t;
		t.ch = it.first;
		t.weight = it.second;
		_huffmanTree.push_back(t);
	}
	int s1 = 0, s2 = 0;
	for (int i = n; i< 2 * n - 1; ++i) {
		huffmannode t;
		selectTwo(_huffmanTree, i, s1, s2); //從前i個(gè)選出兩個(gè)權(quán)重最小的倆個(gè)
		_huffmanTree.at(s1).father = i;
		_huffmanTree.at(s2).father = i;
		t.lc= s1;
		t.rc = s2;
		t.weight = _huffmanTree.at(s1).weight + _huffmanTree.at(s2).weight;
		_huffmanTree.push_back(t);
	}
}
4.根據(jù)哈夫曼樹構(gòu)造譯碼表
void getPassworld(vector& _huffmanTree, map& _passworldMap)
{
	int n = (_huffmanTree.size() + 1) / 2;
	for (int i = 0; i< n; ++i) {
		std::string passworld = "";
		int t = i;
		int fa = _huffmanTree.at(i).father;
		while (fa) {
			if (_huffmanTree.at(fa).lc == t)
				passworld = '0' + passworld;
			else if (_huffmanTree.at(fa).rc == t)
				passworld = '1' + passworld;
			t = fa;
			fa = _huffmanTree.at(t).father;
		}
		_passworldMap.emplace(huffmanTree.at(i).ch, passworld);
	}
}
5.壓縮

得到譯碼表后,將原文的每個(gè)字符(包括中文)翻譯成對應(yīng)的不定長二進(jìn)制字符串,然后以8位為一個(gè)uchar再重新輸入到另一個(gè)文件中即為壓縮后的文件。

//將原文翻譯成二進(jìn)制字符串
std::string binary = "";
	fin.open(fileName, std::ios::in);
	unsigned char c;
	binary = "";
	while (fin.peek()!=EOF)
	{
		c = fin.get();
		std::string s = "";
		if (judgeEng(c))
			s += c;
		else
		{
			s += c;
			c = fin.get();
			s += c;
			c = fin.get();
			s += c;
		}
		binary+=passworldMap[s];
	}
	fin.close();
//將得到的二進(jìn)制字符串每8位轉(zhuǎn)為一個(gè)uchar類型寫入壓縮文件
	for (int i = 0; i< binary.size(); i += 8)
	{
		std::string k = binary.substr(i, 8);
		c = binaryStringToChar(k);
		fout<< c;
	}

在這個(gè)過程中我們需要解決兩個(gè)問題:

1.原文翻譯后的二進(jìn)制字符串長度不是8的倍數(shù)

這個(gè)問題很簡單,不足8位在末尾補(bǔ)0或者1都行。

//在末尾補(bǔ)0 
int add0Num = binary.size() % 8;
	if (add0Num)
		add0Num = 8 - add0Num;
	for (int i = 0; i< add0Num; ++i, binary += '0');

2.壓縮文件如何解壓

因?yàn)樾枰獙嚎s文件解壓,所以我們在壓縮時(shí)還需要加入一些輔助信息,比如哈夫曼樹的權(quán)重圖和上個(gè)問題中末尾補(bǔ)0或1的個(gè)數(shù)都是我們解壓時(shí)需要的。所以在壓縮時(shí)這些信息也需要一同放入壓縮文件中。

// 將 輔助信息寫入壓縮文件中
	fout<< weightMap.size()<< " "<

四、解壓縮

解壓首先要將壓縮文件的輔助信息讀出,并利用輔助信息還原哈夫曼樹和原文翻譯后的二進(jìn)制字符串,然后根據(jù)哈夫曼樹將二進(jìn)制字符串還原。

unsigned char c;
	int size, add0;//字符個(gè)數(shù)和末尾補(bǔ)0的個(gè)數(shù)
	std::map_weightmap;//權(quán)重圖
	fin >>size >>add0;
	fin.get();
	for (int i = 0; i< size; ++i)//從壓縮文件讀取原權(quán)重圖
	{
		std::string s = "";
		int weight = 0;
		c=fin.get();
		if (judgeEng(c))
			s += c;
		else 
		{
			s += c;
			c = fin.get();
			s += c;
			c = fin.get();
			s += c;
		}
		c=fin.get();
		c = fin.get();
		for (; c!= ' '; c=fin.get()) 
		{
			weight = weight * 10 + c - '0';
		}
		_weightmap.emplace(s, weight);
	}

	//還原哈夫曼樹
	std::vector_huffmantree;
	getHuffmanTree(_weightmap, _huffmantree);

	std::string binary = "";
	while (fin.peek()!=EOF)//將壓縮文件的內(nèi)容轉(zhuǎn)為二進(jìn)制字符串
	{
		c = fin.get();
		binary += ucharToBinaryString(c);
	}
	fin.close();

	for (int i = 0; i< add0; binary.pop_back(), ++i);//刪去壓縮時(shí)末尾補(bǔ)充的0
五、效果展示

原文?

壓縮

解壓后

可以看到解壓后的文件和原文一致

完整下載鏈接

https://download.csdn.net/download/yyl1025/87320473?spm=1001.2014.3001.5501

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧

本文標(biāo)題:c++實(shí)現(xiàn)基于哈夫曼編碼的文本(中英混合)壓縮和解壓縮-創(chuàng)新互聯(lián)
網(wǎng)頁網(wǎng)址:http://jinyejixie.com/article8/ddecip.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供服務(wù)器托管、建站公司、網(wǎng)站內(nèi)鏈、ChatGPT、小程序開發(fā)、虛擬主機(jī)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

潍坊市| 龙岩市| 马公市| 应城市| 喀什市| 张掖市| 张掖市| 吉林市| 芮城县| 长武县| 罗江县| 淳安县| 南郑县| 南陵县| 庆阳市| 汝南县| 鲜城| 璧山县| 奉贤区| 嵩明县| 龙泉市| 布拖县| 宽城| 滦南县| 庆元县| 绍兴县| 沙洋县| 大邑县| 察哈| 原平市| 泊头市| 晋中市| 长海县| 绩溪县| 光泽县| 定陶县| 五常市| 阿克陶县| 咸丰县| 汉寿县| 互助|