c语言赫夫曼树的编码与译码,哈夫曼树与编码译码实现
一、哈弗曼樹的基本概念。
哈夫曼樹,又稱最優(yōu)樹,是一類帶權(quán)路徑長(zhǎng)度最短的樹。下面有幾個(gè)概念:
(1)路徑。
樹中一個(gè)結(jié)點(diǎn)到另一個(gè)結(jié)點(diǎn)之間的分支構(gòu)成這兩個(gè)結(jié)點(diǎn)之間的路徑。
(2)路徑長(zhǎng)度。
路徑上的分枝數(shù)目。
(3)樹的路徑長(zhǎng)度。
從樹根到每一個(gè)結(jié)點(diǎn)的路徑長(zhǎng)度之和。
(4)結(jié)點(diǎn)的帶權(quán)路徑長(zhǎng)度。
從該結(jié)點(diǎn)到樹根之間的路徑長(zhǎng)度與結(jié)點(diǎn)上權(quán)的乘積。
(5)樹的帶權(quán)路徑長(zhǎng)度。
樹中所有葉子節(jié)點(diǎn)的帶權(quán)路徑長(zhǎng)度之和。通常記作:
帶權(quán)路徑長(zhǎng)度WPL最小的二叉樹叫做最優(yōu)二叉樹或哈夫曼樹。
二、構(gòu)造哈夫曼樹。
采用哈夫曼法算法構(gòu)造過程為:
(1)根據(jù)給定的n個(gè)權(quán)值{w1,w2,…,wn}構(gòu)成n棵二叉樹的集合F={T1,T2,…,Tn},其中每棵樹Ti中只有一個(gè)帶權(quán)為wi的根結(jié)點(diǎn),其左右子樹均空。
(2)在F中選取兩棵根結(jié)點(diǎn)的權(quán)值最小的樹作為左右子樹構(gòu)造一棵新的二叉樹,且置新的二叉樹的根結(jié)點(diǎn)的權(quán)值為其左、右子樹上根結(jié)點(diǎn)的權(quán)值之和。
(3)在F中刪除這兩棵樹,同時(shí)將新得到的二叉樹加入到F中。
(4)重復(fù)(2)和(3),直到F只含一棵樹為止。
例如權(quán)值為7,5,2,4的結(jié)點(diǎn)構(gòu)造過程為:
------------------------------分割線------------------------------
將C語言梳理一下,分布在以下10個(gè)章節(jié)中:
三、編碼和編碼樹。
1、等長(zhǎng)編碼和不等長(zhǎng)編碼。
(1)等長(zhǎng)編碼。
每個(gè)字符的編碼長(zhǎng)度相同(每個(gè)編碼所含的二進(jìn)制位數(shù)相同)。特點(diǎn)是編(譯)碼容易,抗干擾能力強(qiáng),但長(zhǎng)度不是最短,效率低。
(2)不等長(zhǎng)編碼。
與等長(zhǎng)編碼相對(duì),效率高。若要設(shè)計(jì)長(zhǎng)短不等的編碼(考慮譯碼唯一性),則必須是任一個(gè)字符的編碼都不是另一個(gè)字符的編碼的前綴,這種編碼稱作前綴編碼。
2、哈夫曼編碼。
考慮利用二叉樹來設(shè)計(jì)二進(jìn)制的前綴編碼。約定左分支表示字符0,右分支表示字符1,從根結(jié)點(diǎn)到葉子結(jié)點(diǎn)的路徑上分支字符組成的字符串作為該葉子結(jié)點(diǎn)字符的編碼,可以證明得到的必為二進(jìn)制前綴碼。
考慮如何得到使電文長(zhǎng)度最短的二進(jìn)制前綴編碼。可以看出,設(shè)計(jì)電文總長(zhǎng)最短的二進(jìn)制前綴編碼即以n種字符出現(xiàn)的頻率作權(quán),構(gòu)造一顆哈夫曼樹。
下面給出C++參考代碼:
#include
#include
#include
#include
#include
using namespace std;
struct TNode
{
unsigned int weight;
unsigned int parent;
unsigned int lchild;
unsigned int rchild;
struct TNode() : weight(0), parent(0), lchild(0), rchild(0){}
};
class HuffTree
{
public:
void HuffmanCode(vector &HT, vector &HC, const vector &wgh);
void HuffDecodeing(vector &HT, vector &HC, vector &SrcCode);
private:
void InitHuffTree(vector &HT, const vector &wgh);
void BuildHuffTree(vector &HT, const vector &wgh);
void SelectTwoMin(vector &HT, int n, int &min1, int &min2);
void HuffCodeing(vector &HT, vector &HC, const vector &wgh);
};
void HuffTree::InitHuffTree(vector &HT, const vector &wgh)
{
if (wgh.empty())
{
return;
}
int wghSize = wgh.size();
int m = 2 * wghSize - 1;
HT.resize(m + 1);
for (int i = 1; i <= wghSize; ++i)
{
HT[i].weight = wgh[i - 1];
}
}
void HuffTree::SelectTwoMin(vector &HT, int n, int &min1, int &min2)
{
if (HT.empty())
{
return;
}
multimap wghMap;
multimap::iterator iter;
for (int i = 1; i < n; ++i)
{
if (HT[i].parent == 0)
{
wghMap.insert(make_pair(HT[i].weight, i));
}
}
if (wghMap.size() >= 2)
{
iter = wghMap.begin();
min1 = iter->second;
min2 = (++iter)->second;
}
}
void HuffTree::BuildHuffTree(vector &HT, const vector &wgh)
{
if (HT.empty() || wgh.empty())
{
return;
}
int htSize = HT.size();
int wghSize = wgh.size();
int wghs1, wghs2;
for (int i = wghSize + 1; i < htSize; i++)
{
SelectTwoMin(HT, i, wghs1, wghs2);
HT[wghs1].parent = i;
HT[wghs2].parent = i;
HT[i].lchild = wghs1;
HT[i].rchild = wghs2;
HT[i].weight = HT[wghs1].weight + HT[wghs2].weight;
}
}
void HuffTree::HuffCodeing(vector &HT, vector &HC, const vector &wgh)
{
if (HT.empty() || wgh.empty())
{
return;
}
int n = wgh.size() + 1;
int cha, par;
string codeTmp, code;
for (int i = 1; i < n; i++)
{
code.clear();
codeTmp.clear();
for (cha = i, par = HT[i].parent; par != 0; cha = par, par = HT[par].parent)
{
if (HT[par].lchild == cha)
{
codeTmp = codeTmp + "0";
}
else
{
codeTmp = codeTmp + "1";
}
}
for (int j = codeTmp.size() - 1; j >= 0; --j)
{
code = code + codeTmp[j];
}
HC.push_back(code);
}
}
void HuffTree::HuffDecodeing(vector &HT, vector &HC, vector &SrcCode)
{
if (HT.empty() || HC.empty())
{
return;
}
string codeTmp;
int p, strLen;
for (int i = 0; i < HC.size(); ++i)
{
p = HT.size() - 1;? ? ? ? ? ? ? ? ? ? ? ? //回到根結(jié)點(diǎn)
codeTmp = HC[i];
strLen = codeTmp.size();
for (int j = 0; j < strLen; ++j)
{
if (codeTmp[j] == '0')
{
p = HT[p].lchild;
}
else
{
p = HT[p].rchild;
}
}
SrcCode.push_back(HT[p].weight);
}
}
void HuffTree::HuffmanCode(vector &HT, vector &HC, const vector &wgh)
{
if (wgh.empty())
{
return;
}
InitHuffTree(HT, wgh);
BuildHuffTree(HT, wgh);
HuffCodeing(HT, HC, wgh);
}
總結(jié)
以上是生活随笔為你收集整理的c语言赫夫曼树的编码与译码,哈夫曼树与编码译码实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言double字母,C语言doubl
- 下一篇: 影像之光可期!曝华为测试1英寸怪兽级大底