算法思想
- 为每个字符建立一个叶子节点,并加上其相应的发生频率
- 当有一个以上的节点存在时,进行下列循环
2.1. 把这些节点作为带权值的二叉树的根节点,左右子树为空
2.2. 选择两棵根结点权值最小的树作为左右子树构造一棵新的二叉树,且至新的二叉树的根结点的权值为其左右子树上根结点的权值之和
2.3. 把权值最小的两个根节点移除
2.4. 将新的节点加入队列中 - 最后剩下的节点即为根节点,此时二叉树已经完成
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#define MAX_SIZE 64
typedef struct node {
char data;
int weight;
int parent;
int lchild;
int rchild;
}HTNode;
typedef struct code {
char cd[MAX_SIZE];
int start;
}HCode;
void createHT(HTNode HT[], int n) {
int i, k;
int lnode, rnode;
double min1, min2;
for (i = 0; i < 2 * n - 1; i++) {
HT[i].parent = HT[i].lchild = HT[i].rchild = -1;
}
for (i = n; i <= 2 * n - 2; i++) {
min1 = min2 = 32767;
lnode = rnode = -1;
for (k = 0; k <= i - 1; k++) {
if (HT[k].parent == -1) {
if (HT[k].weight < min1) {
min2 = min1;
rnode = lnode;
min1 = HT[k].weight;
lnode = k;
}
else if (HT[k].weight < min2) {
min2 = HT[k].weight;
rnode = k;
}
}
}
HT[i].weight = HT[lnode].weight + HT[rnode].weight;
HT[i].lchild = lnode;
HT[i].rchild = rnode;
HT[lnode].parent = i;
HT[rnode].parent = i;
}
}
void createHCode(HTNode HT[], HCode HC[], int n) {
int f;
int c;
HCode hc;
for (int i = 0; i < n; i++) {
hc.start = n;
c = i;
f = HT[i].parent;
while (f != -1) {
if (HT[f].lchild == c) {
hc.cd[hc.start] = 0;
hc.start--;
}
if (HT[f].rchild == c) {
hc.cd[hc.start] = 1;
hc.start--;
}
c = f;
f = HT[f].parent;
}
hc.start++;
HC[i] = hc;
}
}
int main() {
printf("请输入哈夫曼叶子结点:");
int N;
scanf("%d", &N);
HTNode HT[MAX_SIZE];
int n = 0;
char data;
int weight;
printf("请输入结点和权值(例如A 1):\n");
while (n / 2 < N) {
scanf("%c %d", &data, &weight);
HT[n / 2].data = data;
HT[n / 2].weight = weight;
n++;
}
createHT(HT, N);
printf("创建成功\n");
for (int i = 0; i < 2 * N - 1; i++) {
printf("%2d ", i);
printf("%3d ", HT[i].weight);
printf("%2d ", HT[i].parent);
printf("%2d ", HT[i].lchild);
printf("%2d \n", HT[i].rchild);
}
printf("\n");
HCode HC[MAX_SIZE];
createHCode(HT, HC, N);
printf("编码成功\n");
for (int i = 0; i < N; i++) {
printf("%c——", HT[i].data);
for (int j = HC[i].start; j <= N; j++) {
printf("%d", HC[i].cd[j]);
}
printf("\n");
}
return 0;
}