赫夫曼編碼(優先佇列實現)

2021-06-26 00:32:41 字數 3214 閱讀 4849

/*

name: 赫夫曼編碼(優先佇列實現) 

author: 巧若拙 

date: 28/09/14 12:17

description: 

採用優先佇列把乙個普通線性表改造成赫夫曼樹,再進行赫夫曼編碼,得到乙個同時記錄了明文和對應編碼的密碼本。

使用優先佇列(最小堆)構造赫夫曼樹是一種高效的方法,比每次都遍歷整個線性表要快很多。

我在構造密碼本時確保密碼本陣列遞增排序,這樣每次插入新結點時可以折半查詢插入,效率較高。

有序的密碼本在把明文編碼成密文時也可以大大提高查詢效率。 

*/#include

#include

#include

#include

#include

#define maxsize 300

#define ok 1

#define error 0

#define true 1

#define false 0 

typedef char elemtype;

typedef int status; //函式型別,其值是函式結果狀態**,如ok等 

typedef struct hnodetype;    //結點結構體

typedef struct hcodetype;    //編碼結構體

void buildminheap(hnodetype hf, int n);//將線性表hf改造成乙個最小堆 

void minheapsiftdown(hnodetype hf, int n, int pos);//向下調整二叉堆的第pos個元素,使其滿足最小堆的特徵 

void huffmantree (hnodetype hf, int n);//將線性表改造成赫夫曼樹

void displaycodebook(hcodetype cb, int n);//顯示密碼本中的明碼和對應密碼資訊 

int insertcodelib(hcodetype cb, int n, elemtype x, char *s, int len);//將新結點插入到密碼本的編碼線性表中 

int hfcoding(hcodetype cb, hnodetype hf, int n);//根據赫夫曼樹進行赫夫曼編碼,生成密碼本

int main(void)

huffmantree (hf, lenhf); //將線性表改造成赫夫曼樹

lencb = hfcoding(codebook, hf, lenhf*2-1);//根據赫夫曼樹進行赫夫曼編碼,生成密碼本

puts("密碼本:"); 

displaycodebook(codebook, lencb);//顯示密碼本中的明碼和對應密碼資訊 

return 0;}/*

函式功能:將線性表改造成赫夫曼樹

初始條件:非遞減線性表hf已經存在 

操作結果:先將原線性表改造成最小堆(優先佇列),然後按照如下順序處理該最小堆:

刪除權重最小的兩個結點,並將他們加入到佇列尾部,將該兩個最小結點的權值相加,生成乙個新結點,並將新結點加入到優先佇列。

不斷調整該最小堆,直到只剩下乙個結點,即得到赫夫曼樹。 

注意:每次產生新結點時,只需設定新結點的權重及孩子結點資訊,雙親結點資訊等赫夫曼樹構造完畢後再統一計算。  

*/void huffmantree (hnodetype hf, int n)

while (front > 0)

//計算父親結點位置 

hf[0].parent = -1;

for (i=0; i}/*

函式功能:將新結點插入到密碼本的編碼線性表中 

初始條件:每個編碼的明文和密文資訊分別記錄在x和s中,len是字串s的長度 

操作結果:先折半查詢插入位置,然後插入新結點,將x和s的資訊複製給新結點,注意s中儲存的結點編碼的路徑是從葉子到根,儲存到密碼本時需要逆序複製 。 

*/int insertcodelib(hcodetype cb, int n, elemtype x, char *s, int len)//採用二分查詢插入排序 

else

}//新資料,執行插入操作 

for (i=n; i>left; i--)

cb[left].code = (char*)malloc(sizeof(char)*(len+1));

if (!cb[left].code) 

for (i=len-1; i>=0; i--) //把s的字串逆序複製到code 

cb[left].code[len] = '\0';

cb[left].data = x;

return n+1;}/*

函式功能:根據赫夫曼樹進行赫夫曼編碼,生成密碼本 

初始條件:赫夫曼樹hf已經存在,n是赫夫曼樹的長度 

操作結果:對赫夫曼樹的葉子結點進行編碼,並儲存到密碼本,返回密碼本長度。

對密碼本中的各個結點採用二分查詢插入,構造非遞減序列,以便於查詢和編碼。 

*/int hfcoding(hcodetype cb, hnodetype hf, int n)

else

j = f;

f = hf[j].parent;

}str[k] = '\0';

top = insertcodelib(cb, top, hf[i].data, str, k);//採用二分查詢插入排序 } }

return top;}/*

函式功能:顯示密碼本中的明碼和對應密碼資訊 

初始條件:密碼本已經存在 

操作結果:顯示密碼本中的明碼和對應密碼資訊。 

*/void displaycodebook(hcodetype cb, int n)}/*

函式功能:向下調整二叉堆的第pos個元素,使其滿足最小堆的特徵 

初始條件:最小堆hf已經存在,只有第pos個元素不滿足特徵 

操作結果:向下調整二叉堆的第pos個元素,使其滿足最小堆的特徵。 

*/void minheapsiftdown(hnodetype hf, int n, int pos)

else

break;

}hf[pos-1] = temp; //將temp向下調整到適當位置 }/*

函式功能:將線性表hf改造成乙個最小堆 

初始條件:線性表hf已經存在

操作結果:將線性表hf改造成乙個最小堆 

*/void buildminheap(hnodetype hf, int n)

}

赫夫曼編碼

include include using namespace std typedef struct htnode,huffmantree 動態分配陣列儲存赫夫曼樹 typedef char huffmancode 動態分配陣列儲存赫夫曼編碼 赫夫曼編碼的演算法實現 void sethuffmant...

赫夫曼編碼

用赫夫曼樹進行編碼是我們處理資料壓縮常用的方法。請同學們用赫夫曼編碼方法儲存你班同學 資料結構 課程的期終考試成績。include include include include define ok 1 define maxnn 100000 typedef struct studentstuden...

赫夫曼編碼

問題r 赫夫曼編碼 思路 對於赫夫曼來說,往左走為0,往右走為1,可以發現每一位就往下走一層。因此整體報文的長度可以用不同報文在樹中的位置來確定,也就是說,符號種類 每個符號在樹中的深度即為整體報文的長度 而ascll碼的位元位長度為符號個數 8 include include include us...