假設某文字文件只包含26個英文本母,應用哈夫曼演算法對該文件進行壓縮和解壓縮操作,使得該文件占用較少的儲存空間。
(1)假設文件內容從鍵盤輸入;
(2)設計哈夫曼演算法的儲存結構;
(3)設計哈夫曼編碼和解碼演算法;
(4)分析時間複雜度和空間複雜度。
根據上述問題描述,可以看出編寫的程式是通過利用二叉樹結構實現哈夫曼編碼和解碼,並且程式需具有以下要求:
(1)初始化:能夠讓使用者輸入字元和相應字元的頻度來初始化,並建立哈夫曼樹。
(2)建立編碼表:利用已經建好的哈夫曼樹進行編碼,並將每個字元的編碼進行輸出,列印哈夫曼編碼表。
(3)解碼:利用已經建好的哈夫曼樹對編碼後的字串進行解碼,並輸出解碼結果。
運用哈夫曼演算法的相關知識解決問題。以使用者輸入的字元作為需要編碼的字元集合,而每個字元對應的頻度則作為該字元的權值,構造一棵哈弗曼編碼樹,規定哈弗曼編碼樹的左分支代表0,右分支代表1,則從根結點到每個葉子結點所經過的路徑組成的0和1的序列便為需要加密字元的編碼。
資料的邏輯結構:樹狀結構。
資料的儲存結構設計:
(1)採用靜態的三叉鍊錶存放。
演算法思想:
申請儲存哈夫曼編碼串的頭指標陣列,申請乙個字元型指標,用來存放臨時的編碼串;
從葉子節點開始向上倒退,若其為它雙親節點的左孩子則編碼標0,否則標1;直到根節點為止,最後把臨時儲存編碼複製到對應的指標陣列所指向的記憶體中。
重複上述步驟,直到所有的葉子節點都被編碼完。
(2)設計乙個結構體element儲存哈夫曼樹中各結點的資訊:
struct element //哈夫曼樹結點的結構體
;示意圖:
weight
chlchild
rchild
parent
編碼表節點結構:
struct hcode
;哈夫曼演算法的抽象資料型別定義:
adt huffman
datamodel
靜態三叉鍊錶儲存資料
operation
select
輸入:哈夫曼樹的三叉鍊錶h
功能:選擇權值最小的兩棵樹
輸出:權值最小的兩棵樹
reverse
輸入:字串
功能:倒置字串
輸出:倒置後的字串
huffmantree
輸入:哈夫曼樹的三叉鍊錶h,字元的權值w,字符集的大小n
功能:構建哈夫曼樹
輸出:無
createcodetable
輸入:哈夫曼樹的三叉鍊錶h,哈夫曼編碼表的三叉鍊錶hc,字符集的大小n
功能:給每個字元建立左右孩子
輸出:哈夫曼編碼表
decode
輸入:二進位制編碼
功能:解碼
輸出:解碼後的字串
endadt
(1)建立哈夫曼樹的偽**如下:
演算法:huffmantree
輸入:需要編譯的字元和該字元的權值
輸出:哈夫曼樹
1.使用者輸入需要編譯的字元和該字元的權值(即其字母的頻度);
2.構造哈夫曼演算法。設計乙個陣列h儲存哈夫曼樹中各結點的資訊;
3.陣列h初始化,將所有結點的孩子域和雙親域的值初始化為-1;
4.陣列h的前n個元素的權值給定值;
5.呼叫select函式選擇權值最小的根結點進行合併,其下標分別為i1,i2;
6.將二叉樹i1,i2合併為一棵新的二叉樹;
7.共進行n-1次合併,直到剩下一棵二叉樹,這棵二叉樹就是哈夫曼樹;
(2)建立編碼表的偽**如下:
演算法:建立編碼表
輸入:哈夫曼樹,編碼表結構,字元個數
輸出:每個字元的內容、權值、左右節點、雙親結點
1.根據已經建立的哈夫曼樹建立編碼表;
2.從葉子結點開始判斷;
2.1如果當前葉子結點的雙親不是根結點,並且是其雙親的左孩子,則編碼為『0』,否則為『1』;
2.2然後往上對其雙親進行判斷,重複操作,直到每個字元編碼完畢;
3.將已經完成的編碼呼叫reserve函式進行倒置;
4.按照「下標n,權值weight,左孩子lchuld,右孩子rchild,雙親parent,字元char;
(3)解碼的偽**如下:
演算法:decode
輸入:二進位制編碼
輸出:對應的字串
1.使用者輸入要解碼的二進位制字串,建立乙個字元陣列儲存輸入的二進位制字元;
2.建立乙個指向待解碼的字串的第1個字元的指標;
3.讀取每乙個字元。設定乙個根結點的指標,從根結點開始判斷;
3.1若字元為『0』,則指向哈夫曼樹當前結點的左孩子;
3.2若字元為『1』,則指向當前結點的右孩子;
3.3直到指標指向的當前結點的左孩子為-1時,輸出符合的字母;
4.輸出解碼結果;
時間複雜度:
1)select函式,時間複雜度o(n)
2)reverse函式,時間複雜度o(n)
3)huffmantree函式,構造哈夫曼樹,時間複雜度o(n!)
4)createcodetable函式,構造和輸出哈夫曼編碼表,時間複雜度o(n)
5)decode函式,解碼,時間複雜度o(n)
#include#include#includeusing namespace std;
struct element
;struct hcode
;int select(element h, int i) //選擇兩個最小的
h[i1].parent = k;
h[i2].parent = k;
h[k].weight = h[i1].weight + h[i2].weight;
h[k].lchild = i1;
h[k].rchild = i2; }}
void createcodetable(element h, hcode hc, int n) //輸出哈弗曼編碼表
huffmantree(h, e, n);
system("pause");
break;
} case 2:
createcodetable(h, hc, n);
system("pause");
break;
case 3:
; cin >> s;
decode(h, hc, n, s);
system("pause");
break;
} default:
cout << "沒有此選項,請重新選擇!" << endl;
哈夫曼編碼 哈夫曼樹
1.定義 哈夫曼編碼主要用於資料壓縮。哈夫曼編碼是一種可變長編碼。該編碼將出現頻率高的字元,使用短編碼 將出現頻率低的字元,使用長編碼。變長編碼的主要問題是,必須實現非字首編碼,即在乙個字符集中,任何乙個字元的編碼都不是另乙個字元編碼的字首。如 0 10就是非字首編碼,而0 01不是非字首編碼。2....
哈夫曼樹 哈夫曼編碼
定義從a結點到b結點所經過的分支序列為從a結點到b結點的路徑 定義從a結點到b結點所進過的分支個數為從a結點到b結點的路徑長度 從二叉樹的根結點到二叉樹中所有結點的路徑長度紙盒為該二叉樹的路徑長度 huffman樹 帶權值路徑長度最小的擴充二叉樹應是權值大的外界點舉例根結點最近的擴充二叉樹,該樹即為...
哈夫曼編碼 哈夫曼樹
哈夫曼樹是乙個利用權值進行優化編碼的乙個比較奇怪的樹,他的實現比較簡單,用途也比較單一。哈夫曼樹的實現,實現要求 通過哈夫曼樹可以保證在編碼過程中不會出現例如 1000和100這樣的編碼規則,否則就會編碼失敗,因為1000和100在某些情況下的編碼會一模一樣。通過哈夫曼樹可以保證權值大的值進行編碼時...