根据题目描述,我们需要实现两个函数:SelectTwoMin和HuffmanCoding。下面是完整的代码实现:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int weight;
int parent;
int lchild;
int rchild;
} HTNode, *HuffmanTree;
typedef char ** HuffmanCode;
void SelectTwoMin(int upbound, HuffmanTree HT, int &s1, int &s2) {
s1 = 0;
s2 = 0;
// 找出第一个未被选择且父节点为0的节点
for (int i = 1; i <= upbound; ++i) {
if (HT[i].parent == 0) {
s1 = i;
break;
}
}
// 找出第二个未被选择且父节点为0的节点
for (int i = s1 + 1; i <= upbound; ++i) {
if (HT[i].parent == 0) {
s2 = i;
break;
}
}
}
void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n) {
if (n <= 1)
return;
int m = 2 * n - 1; // 哈夫曼树的总结点数
HT = (HuffmanTree)malloc((m + 1) * sizeof(HTNode));
for (int i = 1; i <= n; ++i) { // 初始化叶子结点
HT[i].weight = w[i-1];
HT[i].parent = 0;
HT[i].lchild = 0;
HT[i].rchild = 0;
}
for (int i = n + 1; i <= m; ++i) { // 初始化非叶子结点
HT[i].weight = 0;
HT[i].parent = 0;
HT[i].lchild = 0;
HT[i].rchild = 0;
}
// 构建哈夫曼树
for (int i = n + 1; i <= m; ++i) {
int s1, s2;
SelectTwoMin(i - 1, HT, 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(char*));
char *codeBuf = (char*)malloc(n * sizeof(char)); // 缓冲区,用于临时存储编码
codeBuf[n-1] = '\0'; // 结束符
for (int i = 1; i <= n; ++i) {
int startIdx = n - 1; // 编码缓冲区的起始索引
int curNodeIdx= i;
int parentNodeIdx = HT[curNodeIdx].parent;
while (parentNodeIdx != 0) { // 从叶子结点往根节点回溯,生成编码
if (HT[parentNodeIdx].lchild == curNodeIdx)
codeBuf[--startIdx] = '0';
else
codeBuf[--startIdx] = '1';
curNodeIdx = parentNodeIdx;
parentNodeIdx = HT[curNodeIdx].parent;
}
HC[i] = (char*)malloc((n - startIdx) * sizeof(char)); // 分配内存存储编码
strcpy(HC[i], &codeBuf[startIdx]); // 复制编码到哈夫曼编码数组
}
free(codeBuf);
}
int main() {
HuffmanTree ht;
HuffmanCode hc;
int n;
scanf("%d", &n);
int *w = (int *) malloc (n * sizeof(int));
for(int i = 0; i < n; ++ i)
scanf("%d", &w[i]);
HuffmanCoding(ht, hc, w, n);
for (int i = 1; i <= 2 * n - 1; ++ i) {
printf("%d %d %d %d\n",
ht[i].weight, ht[i].parent, ht[i].lchild, ht[i].rchild);
}
for (int i = 1; i <= n; ++ i)
printf("%s\n", hc[i]);
free(w);
free(ht);
for (int i = 1; i <= n; ++i)
free(hc[i]);
return 0;
}
以上代码实现了SelectTwoMin和HuffmanCoding两个函数,可以通过裁判测试程序样例进行验证。
内容由零声教学AI助手提供,问题来源于学员提问




