導航:首頁 > 源碼編譯 > 哈夫曼演算法怎麼用

哈夫曼演算法怎麼用

發布時間:2022-10-07 05:59:24

⑴ 哈夫曼編碼(貪心演算法

參考: 哈夫曼編碼

哈夫曼編碼是一種十分有效的編碼方法,廣泛應用於 數據壓縮
通過採用 不等長 的編碼方式,根據 字元頻率的不同 ,選擇 不同長度的編碼 ,對頻率 越高 的字元採用 越短 的編碼實現數據的高度壓縮。
這種對頻率越高的字元採用越短的編碼來編碼的方式應用的就是貪心演算法的思想。

下面看一個例子:
假如我們有一個包含1000個字元的文件,每個字元佔1個byte(1byte=8bits),則存儲這100個字元一共需要8000bits。這還是有一些大的
那我們統計一下這1000個字元中總共有多少種字元,原來需要8bit來表示一個字元,如果使用更少的位數來表示這些字元,則可以減少存儲空間。
假設這1000個字元中總共有a、b、c、d、e、f共6種字元,使用使用3個二進制位來表示的話,存儲這1000個字元就只需要3000bits,比原來更節省存儲空間。

或許還可以再壓縮一下:
根據字元出現的 頻率 給與字元 不等長 的編碼,頻率越高的字元編碼越短,頻率越低的字元編碼越長。
它不能像等長編碼一樣直接按固定長度去讀取二進制位,翻譯成字元,為了能夠准確讀取翻譯字元,它要求一個字元的編碼不能是另外一個字元的前綴。

假設a、b、c、d、e、f這6個字元出現的頻率依次降低,則我們可以給與他們這樣的編碼

假如字元的出現頻率如圖所示,按照這樣的編碼表示的話,總位數如圖,一共2100bits,更加節省空間了

貪心策略:頻率小的字元,優先入隊。

步驟:
1.將每一個字元作為節點,以出現頻率大小作為權重,將其都放入 優先隊列 中(一個最小堆);
2.每次出隊兩個節點並創建一個父節點,使其權值為剛剛出隊的節點的權值和,並且為兩個節點的父節點(合並)。然後將這個樹入隊。
3.重復操作2,直到隊列中只有一個元素(此時這個元素表示形式應該為一個樹)時,完成創建。

創建好了樹,該怎麼編碼呢?
我們對一個哈夫曼樹,從父節點開始的所有節點,往左邊標0,右邊標1。那麼到達葉子節點的順次編碼就可以找到了。

C:字元集合
Q:優先隊列
EXTRACT-MIN:傳入一個隊列,出隊最小的元素
INSERT:將z插入到Q中

當for循環結束之後,此時隊列中只有一個元素,就是我們需要的哈夫曼樹,最後返回此樹即可。

假設T樹已經是一個最優的樹,假設x、y的頻率小於等於最低處的a、b,然後交換x、a,y、b。

計算代價是否發生變化。
比如這里比較 T 變成 T 』 後代價是否變化,發現代價變小或不變。

同理T』到T』』,又因為T本來假設就是最優的,所以只能相等
所以T』』也應該符合條件,即貪婪演算法,每次取最小的兩個節點出來這種做法是正確的

⑵ 哈夫曼編碼碼長怎麼算

設某信源產生有五種符號u1、u2、u3、u4和u5,對應概率P1=0.4,P2=0.1,P3=P4=0.2,P5=0.1。

霍夫曼編碼是變長編碼,思路:對概率大的編的碼字短,概率小的編的碼字長,這樣一來所編的總碼長就小,這樣編碼效率就高。上面那樣求是不對的,除非你這6個碼字是等概率的,各佔1/6。應該用對應的概率*其對應得碼長,再求和。

實際應用中

除採用定時清洗以消除誤差擴散和採用緩沖存儲以解決速率匹配以外,主要問題是解決小符號集合的統計匹配,例如黑(1)、白(0)傳真信源的統計匹配,採用0和1不同長度遊程組成擴大的符號集合信源。遊程,指相同碼元的長度(如二進碼中連續的一串0或一串1的長度或個數)。

按照CCITT標准,需要統計2×1728種遊程(長度),這樣,實現時的存儲量太大。事實上長遊程的概率很小,故CCITT還規定:若l表示遊程長度,則l=64q+r。

⑶ 如何寫壓縮軟體,運用哈夫曼演算法實現

到文件壓縮大家很容易想到的就是rar,zip等我們常見的壓縮格式。然而,還有一種就是大家在學習數據結構最常見到的哈夫曼樹的數據結構,以前還不知道他又什麼用,其實他最大的用途就是用來做壓縮,也是一些rar,zip壓縮的祖先,稱為哈弗曼壓縮(什麼你不知道誰是哈弗曼,也不知道哈弗曼壓縮,不急等下介紹)。

隨著網路與多媒體技術的興起,人們需要存儲和傳輸的數據越來越多,數據量越來越大,以前帶寬有限的傳輸網路和容量有限的存儲介質難以滿足用戶的需求。

特別是聲音、圖像和視頻等媒體在人們的日常生活和工作中的地位日益突出,這個問題越發顯得嚴重和迫切。如今,數據壓縮技術早已是多媒體領域中的關鍵技術之一。

一、什麼是哈弗曼壓縮

Huffman(哈夫曼)演算法在上世紀五十年代初提出來了,它是一種無損壓縮方法,在壓縮過程中不會丟失信息熵,而且可以證明Huffman演算法在無損壓縮演算法中是最優的。Huffman原理簡單,實現起來也不困難,在現在的主流壓縮軟體得到了廣泛的應用。對應用程序、重要資料等絕對不允許信息丟失的壓縮場合,Huffman演算法是非常好的選擇。

二、怎麼實現哈弗曼壓縮

哈夫曼壓縮是個無損的壓縮演算法,一般用來壓縮文本和程序文件。哈夫曼壓縮屬於可變代碼長度演算法一族。意思是個體符號(例如,文本文件中的字元)用一個特定長度的位序列替代。因此,在文件中出現頻率高的符號,使用短的位序列,而那些很少出現的符號,則用較長的位序列。

故我們得了解幾個概念:

1、二叉樹:在計算機科學中,二叉樹是每個結點最多有兩個子樹的有序樹。通常子樹的根被稱作「左子樹」(left subtree)和「右子樹」(right subtree)。2、哈夫曼編碼(Huffman Coding):是一種編碼方式,哈夫曼編碼是可變字長編碼(VLC)的一種。uffman於1952年提出一種編碼方法,該方法完全依據字元出現概率來構造異字頭的平均長 度最短的碼字,有時稱之為最佳編碼,一般就叫作Huffman編碼。三、哈夫曼編碼生成步驟:

①掃描要壓縮的文件,對字元出現的頻率進行計算。

②把字元按出現的頻率進行排序,組成一個隊列。

③把出現頻率最低(權值)的兩個字元作為葉子節點,它們的權值之和為根節點組成一棵樹。

④把上面葉子節點的兩個字元從隊列中移除,並把它們組成的根節點加入到隊列。

⑤把隊列重新進行排序。重復步驟③④⑤直到隊列中只有一個節點為止。

⑥把這棵樹上的根節點定義為0(可自行定義0或1)左邊為0,右邊為1。這樣就可以得到每個葉子節點的哈夫曼編碼了。

既如 (a)、(b)、(c)、(d)幾個圖,就可以將離散型的數據轉化為樹型的了。

如果假設樹的左邊用0表示右邊用1表示,則每一個數可以用一個01串表示出來。

則可以得到對應的編碼如下:
1-->110
2-->111
3-->10
4-->0
每一個01串,既為每一個數字的哈弗曼編碼。
為什麼能壓縮:
壓縮的時候當我們遇到了文本中的1、2、3、4幾個字元的時候,我們不用原來的存儲,而是轉化為用它們的01串來存儲不久是能減小了空間佔用了嗎。(什麼01串不是比原來的字元還多了嗎?怎麼減少?)大家應該知道的,計算機中我們存儲一個int型數據的時候一般式佔用了2^32-1個01位,因為計算機中所有的數據都是最後轉化為二進制位去存儲的。所以,想想我們的編碼不就是只含有0和1嘛,因此我們就直接將編碼按照計算機的存儲規則用位的方法寫入進去就能實現壓縮了。
比如:
1這個數字,用整數寫進計算機硬碟去存儲,佔用了2^32-1個二進制位
而如果用它的哈弗曼編碼去存儲,只有110三個二進制位。
效果顯而易見。

⑷ 請問怎樣使用哈夫曼樹(pascal語言)

給定n個權值作為n個葉子結點,構造一棵二叉樹,若帶權路徑長度達到最小,稱這樣的二叉樹為最優二叉樹,也稱為哈夫曼樹(Huffman tree)。

Program huffman_tree(input,output);
const max=32767;n=20;m=2*n-1
Type tnode=RECORD
data:integer;
Lc,Rc:integer;
END;
Var tree:ARRAY[0..m] of tnode;
weight:ARRAY[0..n] of integer;
im,num:integer;

procere initial;
var i:integer;
begin
write('First input nun(<',n:2,')');
readln(num);
writeln('Please input weight:');
for i:=0 to num-1 do read(weight[i])
end;

function minimum:integer;
var i:integer;
begin
min:=max;
for i:=0 to num-1 do
if (min>weight[i]) then
begin
min:=weight[i];
im:=i;
end;
weight[im]:=max;
minimum:=min;
end;

procere huffman;
var i,k:integer;
begin
for i:=num to 2*num-1 do
begin
tree[i].Lc:=minimum;
tree[i].Rc:=minimum;
tree[i].data:=tree[i].Lc:+tree[i].Rc;
weight[im]:=tree[i].data
end;
writeln;
writeln('The result of huffman tree:');
k:=1;
for i:=2*num-2 downto num do
begin
write(tree[i].data:6,':',tree[i].Lc:3,tree[i].Rc:3);
if (k mod 3=0) then writeln; k:=k+1;
end
writeln
end;

procere printd;
var i:integer;
begin
write('The weight of tree:');
for i:=0 to num-1 do
write{weight[i]:3}
end;

begin {main}
initial;
printd;
huffman;
end.

⑸ 什麼是哈夫曼演算法

有一種樹形結構叫哈夫曼樹,用哈夫曼樹的方法解編程題的演算法就叫哈夫曼演算法,其實也沒有哈夫曼演算法這個專有名詞了拉,你這么問我就這么跟你講把。它產生的代碼是
#include"stdio.h"
#include"stdlib.h"
#include"string.h"

typedef char ElemType;
typedef struct
{
ElemType elem;
unsigned int m_weight;
unsigned int parent,lchild,rchild;
}HTNode,*HuffmanTree;

typedef char** HuffmanCode;
typedef int Status;
typedef struct weight
{
char elem;
unsigned int m_weight;
}Weight; // save the information of the symbolizes;

void HuffmanCoding(HuffmanTree *,HuffmanCode *,Weight *,int);
void Select(HuffmanTree,int,int *,int *);
void OutputHuffmanCode(HuffmanTree,HuffmanCode,int);

Status main(void)
{
HuffmanTree HT;
HuffmanCode HC;
Weight *w;
char c; // the symbolizes;
int i,n; // the number of elements;
int wei; // the weight of a element;

printf("input the tatol number of the Huffman Tree:" );
scanf("%d",&n);
w=(Weight *)malloc(n*sizeof(Weight));
for(i=0;i<n;i++)
{
printf("input the element & its weight:");
scanf("%1s%d",&c,&wei);
w[i].elem=c;
w[i].m_weight=wei;
}

HuffmanCoding(&HT,&HC,w,n);
OutputHuffmanCode(HT,HC,n);
return 1;

}

void HuffmanCoding(HuffmanTree *HT,HuffmanCode *HC,Weight *w,int n)
{
int i,m,s1,s2,start,c,f;
char *cd;
HuffmanTree p;
if(n<=1)
return;

m=2*n-1;
(*HT)=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
for(i=1;i<=n;++i)
{
(*HT)[i].elem=w[i-1].elem;
(*HT)[i].m_weight=w[i-1].m_weight;
(*HT)[i].parent=(*HT)[i].lchild=(*HT)[i].rchild=0;
}

for(;i<=m;++i)
{
(*HT)[i].elem='0';
(*HT)[i].m_weight=(*HT)[i].parent=(*HT)[i].lchild=(*HT)[i].rchild=0;
}

for(i=n+1;i<=m;++i)
{
Select(*HT,i-1,&s1,&s2);
(*HT)[s1].parent=i;(*HT)[s2].parent=i;
(*HT)[i].lchild=s1;(*HT)[i].rchild=s2;
(*HT)[i].m_weight=(*HT)[s1].m_weight+(*HT)[s2].m_weight;
}

(*HC)=(HuffmanCode)malloc(n*sizeof(char*));
cd=(char *)malloc(n*sizeof(char));
cd[n-1]='\0';
for(i=1;i<=n;++i)
{
start=n-1;
for(c=i,f=(*HT)[i].parent;f!=0;c=f,f=(*HT)[f].parent)
{
if((*HT)[f].lchild==c) cd[--start]='0';
else cd[--start]='1';
}

(*HC)[i]=(char *)malloc((n-start)*sizeof(char));
strcpy((*HC)[i],&cd[start]);
}
}

void Select(HuffmanTree HT,int n,int *s1,int *s2)
{
int i;
(*s1)=(*s2)=0;
for(i=1;i<=n;i++)
{
if(HT[i].m_weight<HT[(*s2)].m_weight&&HT[i].parent==0&&(*s2)!=0)
{
if(HT[i].m_weight<HT[(*s1)].m_weight)
{
(*s2)=(*s1);
(*s1)=i;
}
else (*s2)=i;

}

if(((*s1)==0||(*s2)==0)&&HT[i].parent==0)
{
if((*s1)==0) (*s1)=i;
else if((*s2)==0)
{
if(HT[i].m_weight<HT[(*s1)].m_weight)
{
(*s2)=(*s1);
(*s1)=i;
}
else (*s2)=i;
} // end of else if
} // end of if
} // end of for

if((*s1)>(*s2))
{
i=(*s1);
(*s1)=(*s2);
(*s2)=i;
}
return;
}

void OutputHuffmanCode(HuffmanTree HT,HuffmanCode HC,int n)
{
int i;
printf("\nnumber---element---weight---huffman code\n");
for(i=1;i<=n;i++)
printf(" %d %c %d %s\n",i,HT[i].elem,HT[i].m_weight,HC[i]);
}

⑹ 哈夫曼樹演算法

題目的闡述:以N進制編碼方式對一個英文字串中的字元進行編碼,每個不同的字元其編碼不同.使得由新的編碼替代原串後總碼長最小,且輸入0,1,2,...,N-1構成的數字串後,依照該編碼方式可以正確的對譯出唯一的英文原串.如:N=3英文原串為ABBCBADDACE其對應的一種編碼方式為A:00B:01C:020D:021E:022原串對譯後的編碼為000101020010002102100020022其碼長為27若輸入編碼串0102002200則對應的英文原串為BCEA 分析: 假設英文原串中的字元存放於字元集S中,‖S‖=X,每個字元在字串中出現的概率為W[i],L[i]為字元i的編碼長.依題意得,對S集合中的不同字元進行N進制編碼後要求1)新字串的碼長最短WPL=∑W[i]*L[i]
(i∈1..X)使得在WPL是所有編碼方式中的最小值2)編碼無二義性任意一字元編碼都不為其它字元編碼的前綴 此題以哈夫曼樹來解答是非常適宜的.N為此哈夫曼樹的分叉數,S字元集里的元素即為此N叉哈夫曼樹的葉子,概率W[i]即為葉子結點的權重,從根結點到各葉子結點的路徑長即為該葉子結點的編碼長L[i].由哈夫曼樹的思想可以知道哈夫曼樹的建立是一步到位的貪心法,即權重越大的結點越靠近該樹的根,這樣,出現頻率越大的字元其編碼就越短.但具體應該怎樣建立起此N叉哈夫曼樹呢?我們首先以N=2為例:S={A,B,C,D}W=[3,1,2,1]首先從W中選出兩個最小權,1,1,將其刪去,並以2(即1+1)替代W=[3,2,2];再從新的W中取出兩個最小權,2,2,將其刪去,並以4(即2+2)替代W=[3,4];依此類推,直到W中只一個值時合並結束,此時W=[7]以上兩兩合並的過程即為二叉哈夫曼樹的建立過程,每一次的合並即是將兩棵子樹歸於一個根結點下,於是可以建立二叉樹如下: m0åæ1mmA0åæ1mmC0åæ1mmBD MIN-WPL=3*1+1*3+2*2+1*3=13 從某一根結點出發走向其左子樹標記為0,走向其右子樹標記為1,則可以得到以下編碼A,B,C,D對應的編碼為A:0B:110C:10D:111
N=3時又是怎樣一種情況呢?設S={A,B,C,D,E}W=[7,4,2,5,3}則按權重排序可得S={D,B,E,C,A}W=[7,5,4,3,2]那麼此哈夫曼樹的樹形應為怎樣呢?是以下的左圖,還是右圖,或是兩者均不是mmåâæåæmmllmåæåæCAåælllllmADBEDåæ
lmBåællEC 顯然,要帶權路徑長WPL最短,那麼,此樹的高度就應盡可能的小,由此可知將此樹建成豐滿N叉樹是最合理的,於是我們盡量使樹每一層都為N個分枝.對於這道題的情況,我們具體來分析.按照哈夫曼樹的思想,首先從W中取出權最小的三個值,即2,3,4,並以9(2+3+4)來代替,得到新的W=[9,7,5];再將這三個值合並成9+7+5=21這個結點.於是得到三叉哈夫曼樹如下:måâællmDBåâælllECAWPL=1*7+1*5+2*2+2*3+2*4=30以0..N-1依次標記每個根結點的N個分枝,則可以得到每個字元相對應的編碼:A:22B:1C:21D:0E:20我們發現對於這種情況恰巧每層均為N個分枝,但事實上並非所有的N叉哈夫曼樹都可得到每層N個分枝.例於當N=3,‖S‖=6時就不可能構成一棵每層都為三個分枝的三叉樹.如何來處理這種情況呢?最簡單的處理方式就是添加若干出現概率為0的空字元填補在N叉樹的最下一層,這些權為0的虛結點並無實際意義但卻非常方全便於這棵N叉樹的建立.空字元的添加個數add的計算如下:Y=‖S‖mod(n-1)add=0(Y=1)add=1(Y=0)add=N-Y(Y>1) 虛結點的加入使得權重最小的N-add個字元構成了距根結點最遠的分枝,使其它字元構成的N叉樹保持了豐滿的N叉結構.例:N=3S={A,B,C,D,E,F}W=[1,2,3,4,5,6}則y:=6mod(3-1)=0add=1於是構成N叉樹如下:­為虛結點¡åâællmFEåâællmDCåâæBA­WPL=1*6+1*5+2*4+2*3+3*2+3*1+3*0=33對應編碼為:A:221B:220C:21D:20E:1F:0

⑺ 請描述哈夫曼演算法,並用圖描述構造哈夫曼樹的過程。

這個講的相當清楚。
首先介紹什麼是哈夫曼樹。哈夫曼樹又稱最優二叉樹,是一種帶權路徑長度最短的二叉樹。所謂樹的帶權路徑長度,就是樹中所有的葉結點的權值乘上其到根結點的路徑長度(若根結點為0層,葉結點到根結點的路徑長度為葉結點的層數)。樹的帶權路徑長度記為WPL=(W1*L1+W2*L2+W3*L3+...+Wn*Ln),N個權值Wi(i=1,2,...n)構成一棵有N個葉結點的二叉樹,相應的葉結點的路徑長度為Li(i=1,2,...n)。可以證明哈夫曼樹的WPL是最小的。
哈夫曼在上世紀五十年代初就提出這種編碼時,根據字元出現的概率來構造平均長度最短的編碼。它是一種變長的編碼。在編碼中,若各碼字長度嚴格按照碼字所對應符號出現概率的大小的逆序排列,則編碼的平均長度是最小的。(註:碼字即為符號經哈夫曼編碼後得到的編碼,其長度是因符號出現的概率而不同,所以說哈夫曼編碼是變長的編碼。)
然而怎樣構造一棵哈夫曼樹呢?最具有一般規律的構造方法就是哈夫曼演算法。一般的數據結構的書中都可以找到其描述:
一、對給定的n個權值{W1,W2,W3,...,Wi,...,Wn}構成n棵二叉樹的初始集合F={T1,T2,T3,...,Ti,...,Tn},其中每棵二叉樹Ti中只有一個權值為Wi的根結點,它的左右子樹均為空。(為方便在計算機上實現演算法,一般還要求以Ti的權值Wi的升序排列。)
二、在F中選取兩棵根結點權值最小的樹作為新構造的二叉樹的左右子樹,新二叉樹的根結點的權值為其左右子樹的根結點的權值之和。
三、從F中刪除這兩棵樹,並把這棵新的二叉樹同樣以升序排列加入到集合F中。
四、重復二和三兩步,直到集合F中只有一棵二叉樹為止。
用C語言實現上述演算法,可用靜態的二叉樹或動態的二叉樹。若用動態的二叉樹可用以下數據結構: struct tree{
float weight; /*權值*/
union{
char leaf; /*葉結點信息字元*/
struct tree *left; /*樹的左結點*/
};
struct tree *right; /*樹的右結點*/
};
struct forest{ /*F集合,以鏈表形式表示*/
struct tree *ti; /* F中的樹*/
struct forest *next; /* 下一個結點*/
};
例:若字母A,B,Z,C出現的概率為:0.75,0.54,0.28,0.43;則相應的權值為:75,54,28,43。
構造好哈夫曼樹後,就可根據哈夫曼樹進行編碼。例如:上面的字元根據其出現的概率作為權值構造一棵哈夫曼樹後,經哈夫曼編碼得到的對應的碼值。只要使用同一棵哈夫曼樹,就可把編碼還原成原來那組字元。顯然哈夫曼編碼是前綴編碼,即任一個字元的編碼都不是另一個字元的編碼的前綴,否則,編碼就不能進行翻譯。例如:a,b,c,d的編碼為:0,10,101,11,對於編碼串:1010就可翻譯為bb或ca,因為b的編碼是c的編碼的前綴。剛才進行哈夫曼編碼的規則是從根結點到葉結點(包含原信息)的路徑,向左孩子前進編碼為0,向右孩子前進編碼為1,當然你也可以反過來規定。
這種編碼方法是靜態的哈夫曼編碼,它對需要編碼的數據進行兩遍掃描:第一遍統計原數據中各字元出現的頻率,利用得到的頻率值創建哈夫曼樹,並必須把樹的信息保存起來,即把字元0-255(2^8=256)的頻率值以2-4BYTES的長度順序存儲起來,(用4Bytes的長度存儲頻率值,頻率值的表示範圍為0--2^32-1,這已足夠表示大文件中字元出現的頻率了)以便解壓時創建同樣的哈夫曼樹進行解壓;第二遍則根據第一遍掃描得到的哈夫曼樹進行編碼,並把編碼後得到的碼字存儲起來。 靜態哈夫曼編碼方法有一些缺點:一、對於過短的文件進行編碼的意義不大,因為光以4BYTES的長度存儲哈夫曼樹的信息就需1024Bytes的存儲空間;二、進行哈夫曼編碼,存儲編碼信息時,若用與通訊網路,就會引起較大的延時;三、對較大的文件進行編碼時,頻繁的磁碟讀寫訪問會降低數據編碼的速度。
因此,後來有人提出了一種動態的哈夫曼編碼方法。動態哈夫曼編碼使用一棵動態變化的哈夫曼樹,對第t+1個字元的編碼是根據原始數據中前t個字元得到的哈夫曼樹來進行的,編碼和解碼使用相同的初始哈夫曼樹,每處理完一個字元,編碼和解碼使用相同的方法修改哈夫曼樹,所以沒有必要為解碼而保存哈夫曼樹的信息。編碼和解碼一個字元所需的時間與該字元的編碼長度成正比,所以動態哈夫曼編碼可實時進行。動態哈夫曼編碼比靜態哈夫曼編碼復雜的多,有興趣的讀者可參考有關數據結構與演算法的書籍。
前面提到的JPEG中用到了哈夫曼編碼,並不是說JPEG就只用哈夫曼編碼就可以了,而是一幅圖片經過多個步驟後得到它的一列數值,對這些數值進行哈夫曼編碼,以便存儲或傳輸。哈夫曼編碼方法比較易懂,大家可以根據它的編碼方法,自己編寫哈夫曼編碼和解碼的程序。

⑻ 哈夫曼樹演算法

題目的闡述:以N進制編碼方式對一個英文字串中的字元進行編碼,每個不同的字元其編碼不同.使得由新的編碼替代原串後總碼長最小,且輸入0,1,2,...,N-1構成的數字串後,依照該編碼方式可以正確的對譯出唯一的英文原串.如:N=3英文原串為ABBCBADDACE其對應的一種編碼方式為A:00B:01C:020D:021E:022原串對譯後的編碼為000101020010002102100020022其碼長為27若輸入編碼串0102002200則對應的英文原串為BCEA 分析: 假設英文原串中的字元存放於字元集S中,‖S‖=X,每個字元在字串中出現的概率為W[i],L[i]為字元i的編碼長.依題意得,對S集合中的不同字元進行N進制編碼後要求1)新字串的碼長最短WPL=∑W[i]*L[i] (i∈1..X)使得在WPL是所有編碼方式中的最小值2)編碼無二義性任意一字元編碼都不為其它字元編碼的前綴 此題以哈夫曼樹來解答是非常適宜的.N為此哈夫曼樹的分叉數,S字元集里的元素即為此N叉哈夫曼樹的葉子,概率W[i]即為葉子結點的權重,從根結點到各葉子結點的路徑長即為該葉子結點的編碼長L[i].由哈夫曼樹的思想可以知道哈夫曼樹的建立是一步到位的貪心法,即權重越大的結點越靠近該樹的根,這樣,出現頻率越大的字元其編碼就越短.但具體應該怎樣建立起此N叉哈夫曼樹呢?我們首先以N=2為例:S={A,B,C,D}W=[3,1,2,1]首先從W中選出兩個最小權,1,1,將其刪去,並以2(即1+1)替代W=[3,2,2];再從新的W中取出兩個最小權,2,2,將其刪去,並以4(即2+2)替代W=[3,4];依此類推,直到W中只一個值時合並結束,此時W=[7]以上兩兩合並的過程即為二叉哈夫曼樹的建立過程,每一次的合並即是將兩棵子樹歸於一個根結點下,於是可以建立二叉樹如下: m0�0�2�0�31mmA0�0�2�0�31mmC0�0�2�0�31mmBD MIN-WPL=3*1+1*3+2*2+1*3=13 從某一根結點出發走向其左子樹標記為0,走向其右子樹標記為1,則可以得到以下編碼A,B,C,D對應的編碼為A:0B:110C:10D:111 N=3時又是怎樣一種情況呢?設S={A,B,C,D,E}W=[7,4,2,5,3}則按權重排序可得S={D,B,E,C,A}W=[7,5,4,3,2]那麼此哈夫曼樹的樹形應為怎樣呢?是以下的左圖,還是右圖,或是兩者均不是mm�0�2�0�9�0�3�0�2�0�3mmllm�0�2�0�3�0�2�0�3CA�0�2�0�3lllllmADBED�0�2�0�3 lmB�0�2�0�3llEC 顯然,要帶權路徑長WPL最短,那麼,此樹的高度就應盡可能的小,由此可知將此樹建成豐滿N叉樹是最合理的,於是我們盡量使樹每一層都為N個分枝.對於這道題的情況,我們具體來分析.按照哈夫曼樹的思想,首先從W中取出權最小的三個值,即2,3,4,並以9(2+3+4)來代替,得到新的W=[9,7,5];再將這三個值合並成9+7+5=21這個結點.於是得到三叉哈夫曼樹如下:m�0�2�0�9�0�3llmDB�0�2�0�9�0�3lllECAWPL=1*7+1*5+2*2+2*3+2*4=30以0..N-1依次標記每個根結點的N個分枝,則可以得到每個字元相對應的編碼:A:22B:1C:21D:0E:20我們發現對於這種情況恰巧每層均為N個分枝,但事實上並非所有的N叉哈夫曼樹都可得到每層N個分枝.例於當N=3,‖S‖=6時就不可能構成一棵每層都為三個分枝的三叉樹.如何來處理這種情況呢?最簡單的處理方式就是添加若干出現概率為0的空字元填補在N叉樹的最下一層,這些權為0的虛結點並無實際意義但卻非常方全便於這棵N叉樹的建立.空字元的添加個數add的計算如下:Y=‖S‖mod(n-1)add=0(Y=1)add=1(Y=0)add=N-Y(Y>1) 虛結點的加入使得權重最小的N-add個字元構成了距根結點最遠的分枝,使其它字元構成的N叉樹保持了豐滿的N叉結構.例:N=3S={A,B,C,D,E,F}W=[1,2,3,4,5,6}則y:=6mod(3-1)=0add=1於是構成N叉樹如下:�0�2為虛結點�0�3�0�2�0�9�0�3llmFE�0�2�0�9�0�3llmDC�0�2�0�9�0�3BA�0�2WPL=1*6+1*5+2*4+2*3+3*2+3*1+3*0=33對應編碼為:A:221B:220C:21D:20E:1F:0

⑼ 哈夫曼編碼的應用

哈夫曼編碼(Huffman Coding)是一種編碼方式,以哈夫曼樹—即最優二叉樹,帶權路徑長度最小的二叉樹,經常應用於數據壓縮。在計算機信息處理中,「哈夫曼編碼」是一種一致性編碼法(又稱"熵編碼法"),用於數據的無損耗壓縮。這一術語是指使用一張特殊的編碼表將源字元(例如某文件中的一個符號)進行編碼。這張編碼表的特殊之處在於,它是根據每一個源字元出現的估算概率而建立起來的(出現概率高的字元使用較短的編碼,反之出現概率低的則使用較長的編碼,這便使編碼之後的字元串的平均期望長度降低,從而達到無損壓縮數據的目的)。這種方法是由David.A.Huffman發展起來的。例如,在英文中,e的出現概率很高,而z的出現概率則最低。當利用哈夫曼編碼對一篇英文進行壓縮時,e極有可能用一個位(bit)來表示,而z則可能花去 25個位(不是26)。用普通的表示方法時,每個英文字母均佔用一個位元組(byte),即8個位。二者相比,e使用了一般編碼的1/8的長度,z則使用了 3倍多。倘若我們能實現對於英文中各個字母出現概率的較准確的估算,就可以大幅度提高無損壓縮的比例。

⑽ 哈夫曼演算法

計算過程如圖所示:

閱讀全文

與哈夫曼演算法怎麼用相關的資料

熱點內容
食嬰鬼整部電影 瀏覽:360
印度電影愛經 瀏覽:642
搜播比神馬更好看的影視 瀏覽:82
特警力量同人小說 瀏覽:253
葉天明柳韻為主角的小說全文免費閱讀 瀏覽:929
比愛戀尺度大的電影 瀏覽:135
主人公叫楊凡的小說 瀏覽:860
在船上做皮肉生意的電影 瀏覽:655
倫理電影飛在天上的船 瀏覽:224
求個網址能在線看 瀏覽:549
美國古埃及電影 瀏覽:78
韓國電影成人學院演員有誰 瀏覽:957
美國大胸電影 瀏覽:140
主角重生老北京的小說 瀏覽:199
邵氏100部恐怖影片 瀏覽:101
青春期2裡面的跳舞的歌 瀏覽:37
國產動作愛情片 瀏覽:420
韓國有部特種兵與護士的電影 瀏覽:662
《貪婪》中的日本女演員 瀏覽:477
男主得艾滋病的電影 瀏覽:807