1. 程式人生 > >資料結構——Huffman編碼及譯碼

資料結構——Huffman編碼及譯碼

Huffman編碼及譯碼

1.掌握二叉樹的二叉連結串列存貯結構。

2.掌握Huffman演算法。

要求:

使用檔案儲存初始的文字資料及最終的結果。

  1. 檔名為inputfile1.txt的檔案儲存的是一段英文短文;
  2. 檔名為inputfile2.txt的檔案儲存01形式的編碼段;
  3. 檔名為outputfile1.txt的檔案儲存各字元的出現次數和對應的編碼;
  4. 檔名為outputfile2.txt的檔案儲存對應於inputfile2.txt的譯碼結果。

統計inputfile1.txt中各字元的出現頻率,並據此構造Huffman樹,編制Huffman 碼;根據已經得到的編碼,對01形式的編碼段進行譯碼。

具體的要求:

1.將給定字元檔案編碼,生成編碼,輸出每個字元出現的次數和編碼;

2.將給定編碼檔案譯碼,生成字元,輸出編碼及其對應字元。

輸入資料格式:

詳見要求部分。

輸出資料格式:

outputfile1.txt檔案中:

字元  出現次數  對應的編碼

 a      37         010

 b      130        00

outputfile2.txt檔案中:

This is a example.

分析(如何構造哈夫曼樹):

假設有n個權值,則構造出的哈夫曼樹有n個葉子結點。 n個權值分別設為 w1、w2、…、wn,則哈夫曼樹的構造規則為:


(1) 將w1、w2、…,wn看成是有n 棵樹的森林(每棵樹僅有一個結點);


(2) 在森林中選出兩個根結點的權值最小的樹合併,作為一棵新樹的左、右子樹,且新樹的根結點權值為其左、右子樹根結點權值之和;


(3)從森林中刪除選取的兩棵樹,並將新樹加入森林;


(4)重複(2)、(3)步,直到森林中只剩一棵樹為止,該樹即為所求得的哈夫曼樹。

 如:對 下圖中的六個帶權葉子結點來構造一棵哈夫曼樹,步驟如下(借用一下他人好看的圖):

程式碼如下(vs2012):

#include<iostream>
#include<fstream>
#include<string>
using namespace std;
struct Huffmannode {
	int parent;
	int lc;
	int rc;
	int weight;
};
class Huffmantree {
private:
	Huffmannode*node;
	char* letter;
	int leafnum;
public:
	Huffmantree();
	~Huffmantree();
	Huffmannode*Initialization(int sum, char z[], int w[]);
	void Encord(Huffmannode*node, char tree[], int sum, char z[], int w[]);
	void Decord(Huffmannode*node, int sum, char z[]);
};
Huffmantree::Huffmantree() {
	node = NULL;
	letter = NULL;
	leafnum = 0;
}
Huffmantree::~Huffmantree() {
	delete[]node;
	delete[]letter;
}
Huffmannode*Huffmantree::Initialization(int sum, char z[], int w[]) {
	int min1, min2;
	int loc1, loc2;
	node = new Huffmannode[2 * sum - 1];
	letter = new char[2 * sum - 1];
	for (int i = 0; i<sum; i++) {
		letter[i] = z[i];
		node[i].weight = w[i];
		node[i].parent = -1;
		node[i].lc = -1;
		node[i].rc = -1;
	}
	for (int i = sum; i<2 * sum - 1; i++) {
		loc1 = -1;
		loc2 = -1;
		min1 = 32767;
		min2 = 32767;
		for (int j = 0; j<i; j++) {
			if (node[j].parent == -1) {
				if (node[j].weight<min1) {
					min2 = min1;
					min1 = node[j].weight;
					loc2 = loc1;
					loc1 = j;
				}
				else {
					if (node[j].weight<min2) {
						min2 = node[j].weight;
						loc2 = j;
					}
				}
			}
		}
		node[loc1].parent = i;
		node[loc2].parent = i;
		node[i].lc = loc1;
		node[i].rc = loc2;
		node[i].parent = -1;
		node[i].weight = node[loc1].weight + node[loc2].weight;
	}
	return node;
}
void Huffmantree::Encord(Huffmannode*node, char t[], int sum, char z[], int w[]) {
	char* code;
	code = new char[sum];
	int m = 0;
	int i, n = 0;
	ofstream shuchu;
	shuchu.open("outputfile1.txt", ios::app);
	while (z[n] != '\0') {
		int r, k = 0, q;
		r = n;
		q = n;
		shuchu << z[n] << "   " << w[n] << "   ";
		while (node[r].parent != -1) {
			r = node[r].parent;
			if (node[r].lc == q) {
				code[k] = '0';
				k++;
			}
			else {
				code[k] = '1';
				k++;
			}
			q = r;
		}
		code[k] = '\0';
		k -= 1;
		while (k >= 0) {
			shuchu << code[k];
			k--;
		}
		shuchu << '\n';
		n++;
	}
	shuchu.close();
	ofstream out;
	out.open("inputfile2.txt", ios::app);
	while (t[m] != '\0') {
		int j, s = 0;
		for (i = 0; i<sum; i++) {
			if (t[m] == z[i])break;
		}
		j = i;
		while (node[j].parent != -1) {
			j = node[j].parent;
			if (node[j].lc == i) {
				code[s] = '0';
				s++;
			}
			else {
				code[s] = '1';
				s++;
			}
			i = j;
		}
		code[s] = '\0';
		s -= 1;
		while (s >= 0) {
			out << code[s];
			s--;
		}
		m++;
	}
	out.close();
}
void Huffmantree::Decord(Huffmannode *node, int sum, char z[]) {
	ifstream tree("inputfile2.txt");
	int k = 0;
	char *code = new char[1000];
	while (!tree.eof()) {
		tree >> code[k];
		k++;
	}
	code[k] = '\0';
	tree.close();
	ofstream yima("outputfile2.txt", ios::app);
	k = 0;
	int j = 2 * sum - 1 - 1;
	while (code[k + 1] != '\0') {
		if (code[k] == '0') {
			j = node[j].lc;
		}
		if (code[k] == '1') {
			j = node[j].rc;
		}
		if (node[j].lc == -1) {
			yima << z[j];
			j = 2 * sum - 1 - 1;
		}
		k++;
	}
	yima.close();
}
int main() {
	ifstream in("inputfile1.txt", ios::app);
	char tree[1000] = { 0 };
	char letter[100];
	int count[100] = { 0 };
	int i = 0, t = 0;
	while (!in.eof()) {
		tree[t] = in.get();
		t++;
	}
	tree[t] = '\0';
	int k = 0;
	in.close();
	while (tree[i] != '\0') {
		int m = 0;
		for (int j = 0; j<k; j++) {
			if (tree[i] == letter[j]) {
				count[j]++;
				m = 1;
			}
		}
		if (m == 0) {
			letter[k] = tree[i];
			count[k]++;
			k++;
		}
		i++;
	}
	count[k] = '\0';
	letter[k] = '\0';
	Huffmantree tree1;
	Huffmannode*node = tree1.Initialization(k, letter, count);
	tree1.Encord(node, tree, k, letter, count);
	tree1.Decord(node, k, letter);
}

相關推薦

資料結構——Huffman編碼譯碼

Huffman編碼及譯碼 1.掌握二叉樹的二叉連結串列存貯結構。 2.掌握Huffman演算法。 要求: 使用檔案儲存初始的文字資料及最終的結果。 檔名為inputfile1.txt的檔案儲存的是一段英文短文; 檔名為inputfile2.txt的檔案儲存01

資料結構--Huffman編碼】優先佇列+棧實現

#include<bits/stdc++.h> using namespace std; typedef struct{ int weight; int id; int par,lchild,rchild; }HTNode,*HuffmanTr

資料結構與演算法內功修煉之——為什麼學習資料結構和演算法如何高效的學習資料結構和演算法

什麼是資料結構和演算法 用一句話總結資料結構和演算法,資料結構和演算法是用來儲存資料和處理資料的;其中的儲存指的是通過怎樣的儲存結構來儲存資料,而處理就是通過怎樣的方式或者方法處理資料 為什麼學習資料結構和演算法 寫出更加高效能的程式碼 演算法,是一種解決問題的思路

[資料結構]Trie簡介Python實現

Trie簡介及Python實現 Trie簡介 Python實現 Trie簡介 Trie即字首樹或字典樹,利用字串公共字首降低搜尋時間。速度為 O

SWUST資料結構--哈夫曼譯碼

const int maxvalue=100; const int maxbit=100; const int maxn=100; #include "iostream" #include "stdio.h" #include "stdlib.h" using namespace std; stru

資料結構:棧應用

  棧的定義:      棧是隻能在一端進行資料插入和刪除的線性表。 棧的性質:      後進先出(FILO),後面進去的元素,先出來,先進去的元素後出來 棧的操作:      棧的操作很簡單,就是

Java資料結構-陣列解析類封裝自定義陣列實現

概念: 陣列是Java資料結構中最基本的資料,是儲存 一組長度固定的 同資料型別的集合。 優點: 插入快:對於無序陣列,只需要在陣列末尾增加資料即可。但對於有序陣列,需要查詢到固定的位置,再插入資料,相對無序陣列 結構簡單 缺點: 根據元素值查

Python資料結構——解析樹樹的遍歷

解析樹 完成樹的實現之後,現在我們來看一個例子,告訴你怎麼樣利用樹去解決一些實際問題。在這個章節,我們來研究解析樹。解析樹常常用於真實世界的結構表示,例如句子或數學表示式。 圖 1:一個簡單句的解析樹 圖 1 顯示了一個簡單句的層級結構。將一個句子表示為一個樹,能使我們通過利用子樹來處理句子中的每個獨立的

重溫資料結構:樹 Java 實現

讀完本文你將瞭解到: 資料結構,指的是資料的儲存形式,常見的有線性結構(陣列、連結串列,佇列、棧),還有非線性結構(樹、圖等)。 今天我們來學習下資料結構中的 樹。 什麼是樹 線性結構中,一個節點至多隻有一個頭節點,至多隻有一個尾節點,彼此連線

資料結構演算法實現解析》電子書下載 -(百度網盤 高清版PDF格式)

     作者:高一凡 副書名:配合嚴蔚敏、吳偉民編著的《資料結構》(C語言版) 出版日期:2002-10-1 出版社:其它 頁數:450 ISBN:7-5606-1176-1/TP*0608 檔案格式:PDF 檔案大小:8

縮短迴圈碼(26,16)的編碼譯碼 -- BCH(26,16)

BCH(26,16)編碼與譯碼 我們知道BCH(26,16)的資訊位是前面16位,而校驗位是後面10位。可以修正2位或者1位的隨機錯誤。 其校驗方法與<a href="http://blog.csdn.net/woijal520/article/details/679

資料結構】棧棧的應用

棧 棧是一種先進後出的的特殊線性表,只允許在固定的一端進行插入和刪除元素操作,進行輸入插入和刪除操作的一端稱為棧頂,另一端稱為棧底 下面採用靜態順序表實現的方式簡單封裝一個棧 儲存方式 #define MAX_SIZE 100 typedef int DataT

C語言-資料結構-插入排序優化-原始碼

1. 插入排序的定義及複雜度插入排序的基本思想是:每步將一個待排序的紀錄,按其關鍵碼值的大小插入前面已經排序的檔案中適當位置上,直到全部插入完為止。其時間複雜度為O(n^2)。2. 原始碼執行結果如下圖

線性表資料結構型別定義相關操作總結

1、順序儲存結構(如陣列) 定義: #define MAXSIZE 20 typedef struct{ int data[MAXSIZE]; //假設這裡是整型 int length; //線性表長度 }; 讀取其中某個元素:假設線性順序表已存在,讀取其中第i個元素

資料結構之棧Java實現

一、棧的基本介紹 棧是一種只允許在一端進行插入或刪除的線性表,也就是說先進後出。棧的操作端通常被稱為棧頂,另一端被稱為棧底,棧的插入操作稱為壓棧(push),棧刪除操作稱為出棧(pop)。壓棧是把新元素放到棧頂元素的上面,使之成為新的棧頂元素;出棧則是把棧頂元

資料結構--樹型別樹的基本概念

資料結構中的幾種樹 序號 型別 具體型別 具體型別 具體型別 具體型別 具體型別 1 二叉樹 ⑴二叉樹 ⑵二叉查詢樹 ⑶笛卡爾樹 ⑷T樹

資料結構之一準備預熱3

6.其他知識補充 資料結構: 資料結構是指相互之間存在一種或多種特定關係的資料元素的集合。 資料結構包括3個方面的內容:邏輯結構、儲存結構、對資料的運算 資料的邏輯結構 資料的邏輯結構是對資料之間關係的描述,它與資料的儲存結構

資料結構之一準備預熱

1.介面 介面可以理解為使用者和函式打交道的地方,通過介面使用者輸入了自己的資料,得到了自己想要的結果 2.在進行演算法設計題中的程式碼書寫時,只需寫出一個或多個可以解決問題的有著清楚介面描述的函式即可。 3.資料型別 對於基本資料型別,

動圖+原始碼,演示Java中常用資料結構執行過程原理

最近在整理資料結構方面的知識, 系統化看了下Java中常用資料結構, 突發奇想用動畫來繪製資料流轉過程. 主要基於jdk8, 可能會有些特性與jdk7之前不相同, 例如LinkedList LinkedHashMap中的雙向列表不再是迴環的. HashMap中的單鏈表是尾插, 而不是頭插入等等, 後文不再贅敘

【圖解資料結構】樹樹的遍歷

當你第一次學習編碼時,大部分人都是將陣列作為主要資料結構來學習。 之後,你將會學習到雜湊表。如果你是計算機專業的,你肯定需要選修一門資料結構的課程。上課時,你又會學習到連結串列,佇列和棧等資料結構。這些都被統稱為線性的資料結構,因為它們在邏輯上都有起點和終點。 當你開始學習樹和圖的資料結構時,你會覺得它是