1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #define N 20
5 #define M 2*N-1
6 typedef struct
7 //哈夫曼树的类型定义
8 {
9 int weight;
10 int parent;
11 int LChild;
12 int RChild;
13 }HTNode,HuffmanTree[M+1];
14 typedef char *HuffmanCode[N+1];
15 void CrtHuffmanTree(HuffmanTree ht,int w[],int n)//构造哈夫曼树ht[M+1],w[]存放n个权值
16
17 {
18 int i,k,Lnode,Rnode,Min1,Min2,max=0;
19 int m=2*n-1;
20 for(i=1;i<=n;i++) //叶子结点初始化
21 {
22 ht[i].weight=w[i];
23 ht[i].parent=0;
24 ht[i].LChild=0;
25 ht[i].RChild=0;
26 }
27 /[i]={ w[i],0,0,0};
28 for(i=n+1;i<=m;i++) //非叶子结点初始化
29 /[i]={0,0,0,0};
30 {
31 ht[i].weight=0;
32 ht[i].parent=0;
33 ht[i].LChild=0;
34 ht[i].RChild=0;
35 }
36
37
38 /*
39
40 for(i=1;i<=m;i++)
41 {
42 printf(" %d,",w[i]);
43 }
44 printf(" %n");
45 for(i=1;i<=m;i++)
46 {
47 printf(" %d,",ht[i].weight);
48 }
49 printf(" %d\n",max);
50
51 */
52
53
54
55 for(i=n+1;i<=m;i++)//建立哈夫曼树
56 {
57 Min1=Min2=10000;
58 Lnode=Rnode=0;//Lnode存放最小值的位置,Rnode存放第二最小值的位置
59 for(k=1;k<i;k++)//只在尚未构造二叉树的结点中查找最小的两个结点
60 {
61 if(ht[k].parent==0)
62 {
63 if(ht[k].weight<Min1)//查找当前最小值
64 {
65 Min2=Min1;
66 Rnode=Lnode;
67 Min1=ht[k].weight;
68 Lnode=k;
69 }
70 else
71 if(k!=Lnode&&ht[k].weight<Min2)//查找当前第二最小值
72 {
73 Min2=ht[k].weight;
74 Rnode=k;
75 }
76 }
77 }
78 ht[i].weight=Min1+Min2;
79 ht[i].LChild=Lnode;ht[i].RChild=Rnode;
80 ht[Lnode].parent=i;ht[Rnode].parent=i;
81 }
82 printf("\n哈夫曼树的终态\n序号\tWeight\tParent\tLChild\tRChild\n");
83 for(i=1;i<=m;i++)//测试代码
84 {
85 printf("%d",i);
86 printf(" %d",ht[i].weight);
87 printf(" %d",ht[i].parent);
88 printf(" %d",ht[i].LChild);
89 printf(" %d",ht[i].RChild);
90 printf("\n");
91 }
92 printf("\n");
93
94
95 }
96 void CrtHuffmanCode(HuffmanTree ht,HuffmanCode hc,int n)
97 //从叶子结点到根,逆求每个叶子结点对应的哈夫曼编码,左0右1
98 {
99 char *cd;
100 int i,j,c,p,start;
101 cd=(char *)malloc(n*sizeof(char));
102 cd[n-1]='\0';
103 for(i=1;i<=n;i++)
104 {
105 start=n-1;
106 c=i;p=ht[i].parent; //寻找该叶子结点的父母
107 while(p!=0)
108 {
109 --start;
110 if(ht[p].LChild==c)
111 cd[start]='0';//判断是左边还是右边
112 else
113 cd[start]='1';
114 c=p;p=ht[p].parent;//继续向上倒推
115 }
116 hc[i]=(char *)malloc((n-start)*sizeof(char));
117 //strcpy(hc[i],&cd[start]);
118 for(j=0;j<n-1;j++)
119 {
120 if(cd[j]=='0'||cd[j]=='1')
121 printf("%c",cd[j]);
122 }
123 printf("\t");
124 for(j=0;j<n-1;j++)
125 {
126 cd[j]=' ';
127 }
128 }
129 free(cd);
130 }
131 void main()
132 {
133 HuffmanTree ht1;
134 HuffmanCode hc;
135 char ch[20];
136 int i,a,w[20];
137 printf("请输入字符个数(小于20):");
138 scanf("%d",&a);
139 printf("请输入字符:");
140 getchar();
141 for(i=1;i<=a;i++)
142 {
143 ch[i]=getchar();
144 }
145 getchar();
146 printf("请输入各个字符对应的权值:");
147 for(i=1;i<=a;i++)
148 {
149 scanf("%d",&w[i]);
150 }
151 CrtHuffmanTree(ht1,w,a);
152 printf("\n\t\ts对各字符的哈夫曼树编码\n");
153 printf("\t字符\t");
154 for(i=1;i<=a;i++)
155 {
156 printf("%c\t",ch[i]);
157
158 }
159 printf("\n\t权值\t");
160 for(i=1;i<=a;i++)
161 printf("%d\t",w[i]);
162 printf("\n 哈夫曼编码\t");
163 CrtHuffmanCode(ht1,hc,a);
164 printf("\n");
165 }