折腾了好久,终于搞定了Huffman编码的问题。千里之堤溃于蚁穴。虽然我这不是千里之堤,但是确实是溃于蚁穴。 代码: #include <malloc.h> #include <string.h> #include <iostream> using namespace std; #define MAXSIZE 100 typedef struct { int weight; int parent, lchild, rchild; }HTNode, *HuffmanTree; typedef char **HuffmanCode; void Select(HuffmanTree &HT, int n, int &s1, int &s2); void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n) { //w存放n个字符的权值,构造赫夫曼树,并求出n个字符的赫夫曼编码 if (n <= 1) return ; int m = 2*n-1; int i; HT = (HuffmanTree) malloc((m+1) * sizeof(HTNode)); HuffmanTree p; int s1, s2; for(i = 1, p = HT+1; i <= n; i++, p++, w++) { p->weight = *w; p->lchild = 0; p->rchild = 0; p->parent = 0; } for(; i <= m; ++p,++i) { //原文就是这里出错了。之前写成:for(; i <= m; ++i) p->weight = 0; p->lchild = 0; p->rchild = 0; p->parent = 0; } for(i = n+1; i <= m; ++i) { //选择HT中parent为0且weight最小的两个结点,其序号分别为s1,s2 Select(HT, i-1, s1, s2); HT[s1].parent = i; HT[s2].parent = i; HT[i].lchild = s1; HT[i].rchild = s2; HT[i].weight = HT[s1].weight + HT[s2].weight; } //从叶子到根逆向求每个字符的赫夫曼树编码 HC = (HuffmanCode) malloc( (n+1) * sizeof(HuffmanTree)); char *cd; cd = (char *) malloc(n * sizeof(char)); cd[n-1] = '/0'; for(i = 1; i <= n; i++) { //逐个字符求赫夫曼编码 int start = n-1; for(int c = i, f = HT[i].parent; f != 0; c = f, f = HT[f].parent) { if(HT[f].lchild == c) cd[--start] = '0'; else cd[--start] = '1'; } HC[i] = (char *) malloc((n-start) * sizeof(char)); //动态为第i个字符编码分配空间 strcpy(HC[i], &cd[start]); } free(cd); //打印赫夫编码 for(int k = 1; k <= n; ++k) cout << HC[k] << endl; } void Select(HuffmanTree &HT, int n, int &s1, int &s2) { //选择HT中parent为0且weight最小的两个结点,其序号分别为s1,s2 int tmp1 = 10000, tmp2 = 10000; s1 = s2 = 0; for(int i = 1; i <= n; i++) { if(HT[i].parent == 0) { if (HT[i].weight<tmp1){ tmp2=tmp1; tmp1=HT[i].weight; s2=s1; s1=i; } else if (HT[i].weight<tmp2){ tmp2=HT[i].weight; s2=i; } } } } void main() { HuffmanTree HT; HuffmanCode HC; int n,i; printf("请输入元素个数:"); scanf("%d",&n); int Wt[MAXSIZE]; for(i = 1; i <= n; i++) { printf("请输入权值:"); cin >> Wt[i]; } HuffmanCoding(HT, HC, Wt+1, n); }