哈夫曼树

  1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <malloc.h>
4 #include <string.h>
5 #include <assert.h>
6
7 typedef struct {
8 char info;
9 unsigned int weight;
10 unsigned int parent, lchild, rchild;
11 }HTNode, *HuffmanTree;
12
13 typedef char **HuffmanCode;
14
15 //在HT[1..n]中选择两个weight最小且parent为0的节点,
16 //其序号分别为(*ps1), (*ps2),并且(*ps1)最小,(*ps2)次之。
17 //待改进
18 void
19 Select(HuffmanTree HT, int n, int *ps1, int *ps2)
20 {
21 int i = 1, min, mun;
22 while(HT[i].parent != 0)
23 i++;
24
25 min = mun = i;
26
27 for(; i <= n; i++)
28 {
29 if(HT[i].parent == 0) {
30 if(HT[i].weight < HT[min].weight) {
31 mun = min;
32 min = i;
33 } else if(HT[i].weight < HT[mun].weight) {
34 mun = i;
35 }
36 if(mun == min) {
37 mun++;
38 while(HT[mun].parent != 0)
39 mun++;
40 }
41 }
42 }
43
44 *ps1 = min;
45 *ps2 = mun;
46 }
47
48 void
49 HuffmanCoding(HuffmanTree *pTree, HuffmanCode *pCode, int w[], int n, char info[])
50 {
51 assert(n > 1);
52 int m = 2 * n -1;
53 int i;
54 int s1, s2;
55 int pos;
56 int cur, parent;
57 HTNode *pnode;
58 char *tmp;
59
60 //申请空间。
61 *pTree = (HuffmanTree)malloc((m+1) * sizeof(HTNode));
62 pnode = *pTree + 1;
63
64 for(i = 1; i <= n; i++, pnode++, w++, info++) {
65 //*pnode = {*info, *w, 0, 0, 0};
66 pnode->info = *info;
67 pnode->weight = *w;
68 pnode->parent = 0;
69 pnode->lchild = 0;
70 pnode->rchild = 0;
71 }
72
73 for(; i <=m; i++, pnode++) {
74 //*pnode = {' ', 0, 0, 0, 0};
75 pnode->weight = 0;
76 pnode->parent = 0;
77 pnode->lchild = 0;
78 pnode->rchild = 0;
79 }
80
81 //建立HuffmanTree
82 for(i = n+1; i <= m; i++)
83 {
84 //找出parent为0的两个最小节点序号,s1存放最小的,s2次之
85 Select(*pTree, i-1, &s1, &s2);
86 //设置两个节点
87 (*pTree+s1)->parent = i;
88 (*pTree+s2)->parent = i;
89 (*pTree+i)->weight = (*pTree+s1)->weight + (*pTree+s2)->weight;
90 (*pTree+i)->lchild = s1;
91 (*pTree+i)->rchild = s2;
92 }
93
94 //编码
95 *pCode = (HuffmanCode)malloc((n+1) * sizeof(char *));
96
97 // 最长编码为n-1个字符
98 tmp = (char *)malloc(n * sizeof(char));
99 tmp[n-1] = '\0';
100
101 for(i = 1; i <= n; i++) //n个节点
102 {
103 pos = n - 1; //编码字符串cd游标
104
105 for(cur = i, parent = (*pTree+cur)->parent; parent != 0; cur = parent, parent = (*pTree+parent)->parent)
106 {
107 if(cur == (*pTree+parent)->lchild)
108 tmp[--pos] = '0';
109 else
110 tmp[--pos] = '1';
111 }
112
113 *(*pCode + i) = (char *)malloc(n * sizeof(char));
114 strcpy(*(*pCode+i), &tmp[pos]);
115 }
116
117 free(tmp);
118 }
119
120 void
121 HuffmanTranslateCoding(HuffmanTree HT, int n, char c[])
122 {
123 int i = 0;
124 int m = 2 * n - 1;
125 int j;
126 while(c[i] != '\0')
127 {
128 j = m;
129 while(HT[j].lchild && HT[j].rchild)
130 {
131 if(c[i] == '0')
132 j = HT[j].lchild;
133 else if(c[i] == '1')
134 j = HT[j].rchild;
135 i++;
136 }
137 printf("%c", HT[j].info);
138 }
139 printf("\n");
140 }
141
142 int
143 main(void)
144 {
145 HuffmanTree HT;
146 HuffmanCode Code;
147 int i;
148 int w[] = {1, 2, 4, 6, 8};
149 char info[] = {'a', 'b', 'c', 'd', 'e'};
150 HuffmanCoding(&HT, &Code, w, 5, info);
151
152 for(i = 1; i <= 5; i++)
153 printf("%s-------------\n", Code[i]);
154 HuffmanTranslateCoding(HT, 5, "111");
155 HuffmanTranslateCoding(HT, 5, "1100");
156
157 return 0;
158 }

注意:

1、在主程序里面声明非指针变量,用“&”传递地址,此时已经为该变量分配空间,所以在本地方法里面不用malloc了。声明二级指针后尤其要记得初始化指针,即用malloc分配空间!!!昨天刚犯错,今天又来一次,伤不起了!!!注意值传递,注意指针分配空间。

2、对于数组arr[N], arr[i]相当于i[arr],相当于*(arr+i)。

posted @ 2012-01-01 20:51  leealways87  阅读(201)  评论(0编辑  收藏  举报