DS二叉樹——Huffman編碼與解碼
題目描述
1、問題描述
給定n個字元及其對應的權值,構造Huffman樹,並進行huffman編碼和譯(解)碼。
構造Huffman樹時,要求左子樹根的權值小於、等於右子樹根的權值。
進行Huffman編碼時,假定Huffman樹的左分支上編碼為‘0’,右分支上編碼為‘1’。
2、演算法
構造Huffman樹演算法:
⑴ 根據給定的n個權值(w1, w2, …, wn)構成n棵二叉樹的集合F={T1, T2, …, Tn},其中每棵二叉樹Ti中只有一個權值為wi的根結點。
⑵ 在F中選取兩棵根結點的權值最小的樹,作為左、右子樹構造一棵新的二叉樹,且置其根結點的權值為其左、右子樹權值之和。
⑶ 在F中刪除這兩棵樹,同時將新得到的二叉樹加入F中。
(4) 重複⑵, ⑶,直到F只含一棵樹為止。
3、Huffman編碼演算法:
⑴ 從Huffman樹的每一個葉子結點開始。
⑵ 依次沿結點到根的路徑,判斷該結點是父親結點的左孩子還是右孩子,如果是左孩子則得到編碼‘0’,否則得到編碼‘1’,先得到的編碼放在後面。
⑶ 直到到達根結點,編碼序列即為該葉子結點對應的Huffman編碼。
4、Huffman譯(解)碼演算法:
⑴ 指標指向Huffman樹的根結點,取第一個Huffman碼。
⑵ 如果Huffman碼為‘0’,將指標指向當前結點的左子樹的根結點;如果Huffman碼為‘1’,將指標指向當前結點的右子樹的根結點。
⑶ 如果指標指向的當前結點為葉子結點,則輸出葉子結點對應的字元;否則,取下一個Huffman碼,並返回⑵。
⑷ 如果Huffman碼序列未結束,則返回⑴繼續譯碼。
輸入
第一行測試次數
第2行:第一組測試資料的字元個數n,後跟n個字元
第3行:第一組測試資料的字元權重
待編碼的字串s1
編碼串s2
其它組測試資料類推
輸出
第一行~第n行,第一組測試資料各字元編碼值
第n+1行,串s1的編碼值
第n+2行,串s2的解碼值,若解碼不成功,輸出error!
其它組測試資料類推
樣例輸入
2 5 A B C D E 15 4 4 3 2 ABDEC 00000101100 4 A B C D 7 5 2 4 ABAD 1110110
樣例輸出
A :1 B :010 C :011 D :001 E :000 1010001000011 error! A :0 B :10 C :110 D :111 0100111 DAC
#include <iostream>
#include <string>
#include <cstring>
#include <stack>
using namespace std;
const int maxw = 9999;
class HuffNode{
public:
int weight;
int parent;
int leftchild;
int rightchile;
};
class HuffMan{
private:
void MakeTree()
{
int i, s1, s2;
for (i = lnum + 1; i <= len; i++)
{
SelectMin(i - 1, &s1, &s2);
hufftree[s1].parent = i;
hufftree[s2].parent = i;
hufftree[i].leftchild = s1;
hufftree[i].rightchile = s2;
hufftree[i].weight = hufftree[s1].weight + hufftree[s2].weight;
}
}
void SelectMin(int pos, int *s1, int *s2)
{
int w1, w2, i;
w1 = w2 = maxw;
*s1 = *s2 = 0;
for (i = 1; i <= pos; i++)
{
if (hufftree[i].weight < w1 && hufftree[i].parent == 0)
{
*s2 = *s1;
w2 = w1;
w1 = hufftree[i].weight;
*s1 = i;
}
else if (hufftree[i].weight < w2 && hufftree[i].parent == 0)
{
w2 = hufftree[i].weight;
*s2 = i;
}
}
}
public:
int len;
int lnum;
HuffNode *hufftree;
string *huffCode;
char *message;
void MakeTree(int n, int wt[], char c[])
{
int i;
lnum = n;
len = 2 * n - 1;
hufftree = new HuffNode[2 * n];
huffCode = new string[lnum + 1];
message = new char[lnum + 1];
for (i = 1; i <= n; i++)
hufftree[i].weight = wt[i - 1];
for (i = 1; i <= n; i++)
message[i] = c[i - 1];
for (i = 1; i <= len; i++)
{
if (i > n)
hufftree[i].weight = 0;
hufftree[i].parent = 0;
hufftree[i].leftchild = 0;
hufftree[i].rightchile = 0;
}
MakeTree();
}
void Coiding()
{
char *cd = new char[lnum];
int i, c, f, start;
cd[lnum - 1] = '\0';
for (i = 1; i <= lnum; i++)
{
start = lnum - 1;
for (c = i, f = hufftree[i].parent; f != 0; c = f, f = hufftree[f].parent)
{
if (hufftree[f].leftchild == c)
cd[--start] = '0';
else
cd[--start] = '1';
}
huffCode[i].assign(&cd[start]);
}
}
void Destory()
{
len = 0;
lnum = 0;
delete[]hufftree;
delete[]huffCode;
}
int Decode(const string codestr, string &teststr){
int i, k, c;
char ch;
c = len;
k = 0;
string a = "";
for (i = 0; i < codestr.length(); i++)
{
ch = codestr[i];
a += ch;
if (ch == '0') c = hufftree[c].leftchild;
else
if (ch == '1')
c = hufftree[c].rightchile;
else
return 0;
if (hufftree[c].leftchild == 0 && hufftree[c].rightchile == 0)
{
for (int j = 1; j <= lnum; j++)
if (hufftree[c].weight == hufftree[j].weight && a == huffCode[j])
teststr += message[j];
c = len;
a = "";
}
else ch = '\0';
}
if (ch == '\0') return 0;
return 1;
}
};
int main()
{
int t, n, i, j;
int wt[800];
char c[800];
string teststr = "";
string codestr;
HuffMan huff;
cin >> t;
while (t--)
{
cin >> n;
for (i = 0; i < n; i++) cin >> c[i];
for (i = 0; i < n; i++) cin >> wt[i];
huff.MakeTree(n, wt, c);
huff.Coiding();
for (i = 1; i <= n; i++)
{
cout << c[i - 1] << " :" << huff.huffCode[i] << endl;
}
cin >> codestr;
for (i = 0; i < codestr.length(); i++)
{
for (j = 1; j <= n; j++)
if (codestr[i] == c[j - 1]) cout << huff.huffCode[j];
}
cout << endl;
cin >> codestr;
if (huff.Decode(codestr, teststr)) cout << teststr << endl;
else cout << "error!" << endl;
teststr = "";
huff.Destory();
}
return 0;
}
相關推薦
DS二叉樹——Huffman編碼與解碼
題目描述 1、問題描述 給定n個字元及其對應的權值,構造Huffman樹,並進行huffman編碼和譯(解)碼。 構造Huffman樹時,要求左子樹根的權值小於、等於右子樹根的權值。 進行Huffman編碼時,假定Huffman樹的左分支上編碼為‘0’,右
DS二叉樹--赫夫曼樹的構建與編碼
題目描述 給定n個權值,根據這些權值構造huffman樹,並進行huffman編碼 參考課本演算法,注意陣列訪問是從位置1開始 要求:赫夫曼的構建中,預設左孩子權值不大於右孩子權值 輸入 第一行輸入t,表示有t個測試例項 第二行先輸入n,表示第1個例項有n個權
DS二叉樹--赫夫曼樹解碼
題目描述 已知赫夫曼編碼演算法和程式,在此基礎上進行赫夫曼解碼 在赫夫曼樹的類定義中增加了一個公有方法: int Decode(const string codestr, char txtstr[]); //輸入編碼串codestr,輸出解碼串txtstr
【數據結構與算法】二叉樹遞歸與非遞歸遍歷(附完整源碼)(轉)
style stack gravity text 一個 eat 遞歸遍歷 deb 雙向 轉自:http://blog.csdn.net/ns_code/article/details/12977901 二叉樹是一種非常重要的數據結構,很多其他數據機構都是基於二叉樹的基礎
[javaSE] 數據結構二叉樹-遍歷與查找
ngx quest wan ase ngs san http zhong ros %E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A8%8B%E5%BA%8F%E7%9A%84%E6%80%9D%E7%BB%B4%E9%80%BB%E8%BE%91%2018%
二叉樹(性質與存儲)
tco img 分享圖片 pos 技術 master blog lee mar 二叉樹的性質及存儲如下 二叉樹(性質與存儲)
【資料結構】二叉樹的建立與遍歷(遞迴)
該程式全是使用遞迴的操作 執行環境是:Dev-C++ #include <stdio.h> #include <stdlib.h> typedef struct node{ char data; struct node *lchild,*rchild; }bi
二叉樹(建立與訪問)(先序,中序,後序)
二叉樹的建立(先序建立) 二叉樹的訪問(遞迴與非遞迴 先序)(遞迴與非遞迴中序)(遞迴與非遞迴 後序) #include<iostream> #include<stack> using namespace std; struct Tree_Node ///結點的
第六章樹和二叉樹--Huffman樹-計算機17級
解析在下面,有什麼問題歡迎各位大佬指正 p1-1: 這個主要得看懂題,其實就是在考你哈夫曼樹的構造:每次把權值最小的兩顆二叉樹合併 ,越往下肯定權值越小,所以這句話肯定是對的 x2-1: d肯定不一定啊 x2-2: x2-3:
第六章樹和二叉樹--Huffman樹
1-1 對N(≥2)個權值均不相同的字元構造哈夫曼樹,則樹中任一非葉結點的權值一定不小於下一層任一結點的權值。 (2分) T 2-1 對N(N≥2)個權值均不相同的字元構造哈夫曼樹。下列關於該哈夫曼樹的敘述中,錯誤的是: (2分) 樹中一
二叉樹(0)——二叉樹的實現與二叉樹的遍歷
0.二叉樹的實現(C++) 未完,待補充 #include <iostream> #include<iostream> #include<queue> #include<stack> using namespace std; //二叉樹結點的
資料結構——二叉樹的建立與遞迴遍歷
#include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct Node{ //二叉樹的鏈式儲存結點 char data; struct Node *Lch
二叉樹的建立與遍歷(先序,中序,後序,層次)
#include<stdio.h> #include<stdlib.h> typedef struct BitNode { char data; struct BitNode *lchild,*rchild; }BitNode; BitNode* Crea
資料結構 筆記:二叉樹的比較與相加
二叉樹的克隆操作 -SharedPointer<BTree<T>> clone() const ·克隆當前樹的一份拷貝 ·返回值為堆空間中的一棵新二叉樹(與當前樹相等) 二叉樹的克隆 -定義功能:clone(node) ·拷貝node為根節點的二叉樹(
學習筆記 c++ (用類來實現二叉樹的建立與遍歷)
程式碼: #include<iostream> #include<stdio.h> using namespace std; class BiTree { public: char data; BiTree *
【資料結構週週練】010 遞迴演算法實現二叉樹的建立與遍歷
一、前言 上兩篇週週練部落格講了二叉樹的建立與遍歷,建立時,通過建立棧來存放結點,方便二叉樹的建立,這種建立二叉樹的方式採用了非遞迴演算法,本次內容採用遞迴的方式來建立二叉樹,大家可以通過對比程式碼量,感受一下遞迴的魅力。同時遍歷過程也是通過遞迴演算法。 如果大家第一次看
二叉樹的建立與實現
#include <iostream> #include<cstdio> #include<cstdlib> using namespace std; typedef int TelemType;//TelemType代替int ty
1. 二叉樹的建立與基本操作
1. 二叉樹的建立與基本操作 成績 10 開啟時間 2018年10月28日 星期日 18:00 折扣 0.8 折扣時間 2018年11月18日 星期日 23:55
二叉樹的建立與遍歷
#include<iostream> #include<cstring> #include<conio.h> #include<cstdlib> #define OK 1 #define ERROR 0 #define OVER
哈夫曼樹的編碼與解碼
#include<stdio.h> #include<stdlib.h> #include<iostream> #include<string> using namespace std; #define MAXSIZE 30