1. 問題描述:
利用哈夫曼編碼進行通訊可以大大提高通道利用率,縮短資訊傳輸時間,降低傳輸成本。但是,這要求在傳送端通過乙個編碼系統對待傳資料預先編碼,在接收端將傳來的資料進行解碼(解碼)。對於雙工通道(即可以雙向傳輸資訊的通道),每端都需要乙個完整的編/解碼系統。試為這樣的資訊收發站設計乙個哈夫曼編/解碼系統。
2.乙個完整的系統應具有以下功能:
1)初始化(initialzation)。從資料檔案 datafile.data 中讀入字元及每個字元的權值,建立哈夫曼樹 hufftree;
2)編碼(encoding)。用已建好的哈夫曼樹,對檔案 tobetran.data 中的文字進行編碼形成報文,將報文寫在檔案 code.txt 中;
3)解碼(decoding)。利用已建好的哈夫曼樹,對檔案 codefile.data 中的**進行解碼形成原文,結果存入檔案 textfile.txt 中;
4)輸出(output): 輸出tobetran.data 及其報文 code.txt;輸出 codefile.data 及其原文 textfile.txt;
要求:所設計的系 統應能在程 序執行的過程中,根據 實際情況(不同的輸入 )建立datafile.data、tobetran.data 和 codefile.data 三個檔案,以保證系統的通用性。
程式設計思想:
1)根據哈夫曼樹的定義:有n個葉子節點的哈夫曼樹必有m = 2 * n - 1個節點。
構造哈夫曼樹時:將前n個節點初始化相應的字元和權值,從中找到兩個父母節點為0(意味著未被訪問過)且權值最小的兩個數作為第n+1個節點的左右孩子,依次初始化剩餘m-n個節點。
2)根據哈夫曼樹的定義:有n個葉子節點的哈夫曼樹其深度不會超過n-1。
編碼時:1.定義臨時存放哈夫曼編碼的陣列cd,從葉到根逆向求編碼,將得到的資料倒著存入陣列cd中,再將陣列cd拷貝到hc中,2.再找下乙個葉節點,將得到的資料再倒著存入陣列cd中,再將陣列cd拷貝到hc中。重複2,最後不要忘了釋放cd的空間。
3)解碼時:依據編碼向下遍歷樹,直到向下碰到葉子節點。
4)輸出檔案內容時:用乙個陣列儲存檔名。
注意!!!
執行:
#include
"stdio.h"
#include
"stdlib.h"
#include
"string.h"
#define n 100
#define error 0
#define ok 1
typedef
struct
htnode,
*huffmantree;
//動態分配陣列儲存哈夫曼樹
typedef
char
**huffmancode;
//用於儲存哈夫曼編碼的陣列
void
select
(huffmantree &ht,
int i,
int&s1,
int&s2)
for(j =
1;j <= i;j++)if
(ht[j]
.parent ==0)
if(ht[j]
.weight < ht[temp]
.weight)
//設temp為最小節點
temp=j;
//如果比temp小,則交換
s1 = temp;
//找權值次小節點
for(k =
1;k <= i;k++
)//再找父母為0的節點temp
if(ht[k]
.parent ==
0&& k != s1)
for(k =
1;k <= i;k++)if
(ht[k]
.parent ==
0&& k != s1)
//找不與s1相等的最小節點
if(ht[k]
.weight < ht[temp]
.weight)
temp=k;
s2 = temp;
}void initialzation (huffmantree &ht,
int n)
if(n <1)
return
; m =
2* n -1;
ht =
(huffmantree)
malloc
((m +1)
*sizeof
(htnode));
for(i =
1;i <= m;i++
)//0號不用,進行初始化
ht[i]
.parent = ht[i]
.lchild = ht[i]
.rchild =0;
for(i =
1;i <= n;i++
)//建n棵僅含根結點的二叉樹的森林
fscanf
(fp,
"%d%c"
,&ht[i]
.weight,
&ht[i]
.ch)
;fclose
(fp)
;for
( i = n +
1;i <= m;i++
)//建哈夫曼樹
}void encoding (huffmantree ht,huffmancode &hc,
int n)
hc[i]=(
char*)
malloc
((n-start)
*sizeof
(char))
;//為第i個字元編碼分配空間
strcpy
(hc[i]
,&cd[start]);
//從cd複製編碼串到hc[i]中
}free
(cd)
;//釋放工作空間if(
(fp =
fopen
("tobetran.txt"
,"r"))
==null)if
((fp1 =
fopen
("code.txt"
,"w"))
==null
) c =
fgetc
(fp)
;while
(c !=
'#')
c =fgetc
(fp);}
fprintf
(fp1,
"#")
;fclose
(fp)
;fclose
(fp1);}
void
decoding
(huffmantree ht, huffmancode hc,
int n)if(
(fp1 =
fopen
("textfile.txt"
,"w"))
==null
) b =
fgetc
(fp)
;//從檔案中乙個乙個讀取字元
i =2* n -1;
while
(b !=
'#')
b =fgetc
(fp)
;//再讀下乙個字元
}fprintf
(fp1,
"#")
;//將『#』寫入檔案
fclose
(fp)
;//關閉檔案
fclose
(fp1);}
void
print
(char
*filename)
char b =
fgetc
(fp)
;while
(b !=
'#')
fclose
(fp);}
intmain()
}return ok;
}
哈夫曼編碼 哈夫曼樹
1.定義 哈夫曼編碼主要用於資料壓縮。哈夫曼編碼是一種可變長編碼。該編碼將出現頻率高的字元,使用短編碼 將出現頻率低的字元,使用長編碼。變長編碼的主要問題是,必須實現非字首編碼,即在乙個字符集中,任何乙個字元的編碼都不是另乙個字元編碼的字首。如 0 10就是非字首編碼,而0 01不是非字首編碼。2....
哈夫曼樹 哈夫曼編碼
定義從a結點到b結點所經過的分支序列為從a結點到b結點的路徑 定義從a結點到b結點所進過的分支個數為從a結點到b結點的路徑長度 從二叉樹的根結點到二叉樹中所有結點的路徑長度紙盒為該二叉樹的路徑長度 huffman樹 帶權值路徑長度最小的擴充二叉樹應是權值大的外界點舉例根結點最近的擴充二叉樹,該樹即為...
哈夫曼編碼 哈夫曼樹
哈夫曼樹是乙個利用權值進行優化編碼的乙個比較奇怪的樹,他的實現比較簡單,用途也比較單一。哈夫曼樹的實現,實現要求 通過哈夫曼樹可以保證在編碼過程中不會出現例如 1000和100這樣的編碼規則,否則就會編碼失敗,因為1000和100在某些情況下的編碼會一模一樣。通過哈夫曼樹可以保證權值大的值進行編碼時...