先構建哈夫曼樹,再用哈夫曼樹進行編碼。
在這哈夫曼樹不使用鍊錶儲存,而是使用陣列下標方式的儲存結構,即lchild、rchild、parent中儲存的是相應元素對應的下標值。
而編碼結果用陣列儲存,一維陣列中儲存的是對應編碼字串的首位址,這樣可以實現邊長的儲存。
typedef struct htnodehtnode,*huffmantree;
typedef char** huffmancode;
哈夫曼樹不是滿二叉樹(每一層都是滿的),也不是完全二叉樹(深度為n,n-1層是滿的,剩餘的先左再右)。其葉子結點數n與結點樹總和m的關係m=2*n-1,因為哈夫曼樹的所有結點的度都為0或者2,從分叉數來看,一共有(n-1)*2個分叉,分叉數+1等於結點數,所以m=(n-1)*2+1=2*n-1個。
接下來,前n個結點的weight初始化為權重值,剩餘lchild、rchild和parent初始化為-1,n-m個結點全初始化為-1。
構建哈夫曼樹的時候,對於第n-m個結點,每次從前面parent為-1的結點中選取最小的兩個結點,求和,並設定結點的parent,與設定當前結點的值。
int m = 2 * n - 1;
ht = (huffmantree)malloc(sizeof(htnode)*m);
huffmantree p = ht;
for (int i = 0; i < n; i++, p++);
}for (int i = n; i < m; i++, p++);
}p = ht + n;
int h1, h2;
for (int i = n; i < m; i++, p++);
}
從parent != -1 的所有結點中選出兩個最小的:
void selecttwo(huffmantree ht, int &p1, int &p2, int length)
}for (int i = 0; i < length; i++)
if (ht[i].parent == -1 && ht[i].weight < min2)
}}
編碼需要注意的是,從葉子結點向根結點,反向尋找編碼,因為這樣方便判斷到底是左結點的0還是右結點的1編碼。
同時,字串的結尾為』\0』,不要忘記了!!
hc = (huffmancode)malloc(sizeof(char*)*n);
char *str = (char*)malloc(sizeof(char)*(n + 1));
str[n] = '\0';
for (int i = 0; i < n; i++)
else
}hc[i] = (char*)malloc(sizeof(char)*n - index);
strcpy(hc[i], &str[index]);
}
哈夫曼編碼 哈夫曼樹
1.定義 哈夫曼編碼主要用於資料壓縮。哈夫曼編碼是一種可變長編碼。該編碼將出現頻率高的字元,使用短編碼 將出現頻率低的字元,使用長編碼。變長編碼的主要問題是,必須實現非字首編碼,即在乙個字符集中,任何乙個字元的編碼都不是另乙個字元編碼的字首。如 0 10就是非字首編碼,而0 01不是非字首編碼。2....
哈夫曼樹 哈夫曼編碼
定義從a結點到b結點所經過的分支序列為從a結點到b結點的路徑 定義從a結點到b結點所進過的分支個數為從a結點到b結點的路徑長度 從二叉樹的根結點到二叉樹中所有結點的路徑長度紙盒為該二叉樹的路徑長度 huffman樹 帶權值路徑長度最小的擴充二叉樹應是權值大的外界點舉例根結點最近的擴充二叉樹,該樹即為...
哈夫曼編碼 哈夫曼樹
哈夫曼樹是乙個利用權值進行優化編碼的乙個比較奇怪的樹,他的實現比較簡單,用途也比較單一。哈夫曼樹的實現,實現要求 通過哈夫曼樹可以保證在編碼過程中不會出現例如 1000和100這樣的編碼規則,否則就會編碼失敗,因為1000和100在某些情況下的編碼會一模一樣。通過哈夫曼樹可以保證權值大的值進行編碼時...