/*功能,P147,資料結構C語言版,赫夫曼樹和赫夫曼編碼的儲存表示。《演算法設計技巧與分析-沙特》V1cn,p158,講到赫夫曼樹演算法是一種貪心演算法,演算法時間複雜度是O( n logn )。日期:2013年1月5日 星期六部落格,http://blog.csdn.net/shunqiziranhao007/article/details/7804488環境:win7-32-vs2010*/#include <stdio.h>#include <malloc.h>#include <string.h>#include <limits.h>// 赫夫曼樹和赫夫曼編碼的儲存表示typedef struct{unsigned int weight;unsigned int parent, lchild, rchild;} HTNode, *HuffmanTree;// 動態分配數組儲存赫夫曼編碼錶typedef char **HuffmanCode;// select調用它int min1(HuffmanTree t, int i){int j;int flag = -1;// k為最小權值,輔助變數unsigned int k = UINT_MAX;for(j = 1; j <= i; j++){if(t[j].weight < k && t[j].parent == 0)k = t[j].weight, flag = j;}t[flag].parent = 1;return flag;}// s1為最小的兩個元素中序號小的那個void select(HuffmanTree t, int i, int *s1, int *s2){int j;*s1 = min1(t, i);*s2 = min1(t, i);if(*s1 > *s2){j = *s1;*s1 = *s2;*s2 = j;}}// 演算法6.12 P147// w存放n個字元的權值(均>0),構造赫夫曼樹HT,並求出n個字元的赫夫曼編碼HCvoid HuffmanCoding(HuffmanTree *HT, HuffmanCode *HC, int *w, int n){int m, i, s1, s2, start;unsigned c, f;HuffmanTree p;char *cd;if(n <= 1)return;// 一棵有n個葉子結點的赫夫曼樹共有2n-1個結點m = 2*n - 1;// 0號單元未用*HT = (HuffmanTree)malloc( (m+1) * sizeof(HTNode));// 初始化結點for(p = *HT + 1, i = 1; i <= n; ++i, ++p, ++w){(*p).weight = *w;(*p).parent = 0;(*p).lchild = 0;(*p).rchild = 0;}// 繼續初始化後面結點的雙親位置for( ; i <= m; ++i, ++p)(*p).parent = 0;// 建赫夫曼樹for(i = n + 1; i <= m; ++i){// 在HT[1 ~ i-1]中選擇parent為0且weight最小的兩個結點,其序號分別為// s1 和 s2select(*HT, i-1, &s1, &s2);(*HT)[s1].parent = (*HT)[s2].parent = i;(*HT)[i].lchild = s1;(*HT)[i].rchild = s2;(*HT)[i].weight = (*HT)[s1].weight + (*HT)[s2].weight;}// 從葉子到根逆向求每個字元的赫夫曼編碼([0]不用)*HC = (HuffmanCode)malloc( (n+1) * sizeof(char*) );// 分配n個字元編碼的頭指標向量([0]不用)cd = (char*)malloc(n * sizeof(char) );// 編碼結束符cd[n-1] = '\0';// 逐個字元求赫夫曼編碼for(i = 1; i <= n; i++){start = n-1; // 編碼結束符位置for(c = i, f = (*HT)[i].parent; f != 0; c = f, f = (*HT)[f].parent){// 從葉子到根逆向求編碼if((*HT)[f].lchild == c)cd[--start] = '0';elsecd[--start] = '1';}// 為第i個字元的編碼分配空間(*HC)[i] = (char*)malloc( (n-start) * sizeof(char) );// 從cd複製編碼(串)到HCstrcpy_s( (*HC)[i], (n-start), &cd[start]);}free(cd);}int main(){HuffmanTree HT;HuffmanCode HC;int *w, n, i;printf("請輸入權值的個數(>1):");scanf_s("%d", &n);w = (int*)malloc(n * sizeof(int));printf("請依次輸入%d個權值(整型):\n",n);for(i = 0; i <= n-1; i++)scanf_s("%d", w + i);HuffmanCoding(&HT, &HC, w, n);for(i = 1; i <= n; i++)puts(HC[i]);return 0;}/*輸出效果:請輸入權值的個數(>1):4請依次輸入4個權值(整型):7 5 2 4010110111請按任意鍵繼續. . .*/