/*
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...