6-1 哈夫曼树及哈夫曼编码 (10 分)
函数SelectTwoMin(int upbound, HuffmanTree HT, int &s1, int &s2)是从1到upbound中找出father为0的节点赋给s1,s2,(为了保证答案唯一,请让s1的节点编号小于s2),函数HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n)是构造哈夫曼树以及计算哈夫曼编码。保证输入的权重值小于1000。
函数接口定义:
void SelectTwoMin(int upbound, HuffmanTree HT, int &s1, int &s2);
void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n);
其中 upbound 编号,HT是哈夫曼树,HC是哈夫曼编码,w是权值,n是叶子节点个数。
裁判测试程序样例:
#include
#include
#include
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);
void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n);
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;
}
/* 你的代码将被嵌在这里 */
输入格式:
第一行输入一个数n,表示叶子节点的个数,接下去输入n个整数,表示每个节点的值
输出格式:
只要建树即可,输出已经确定了
输入样例:
4
1 2 3 4
输出样例:
1 5 0 0
2 5 0 0
3 6 0 0
4 7 0 0
3 6 1 2
6 7 3 5
10 0 4 6
110
111
10
0
代码如下:
#include
#include
#include
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);
void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n);
void reverse(char *CH)
{
int n=strlen(CH);
int i;
for (i=0; i<n/2;i++)
{
char temp;
temp = CH[i];
CH[i] = CH[n-i-1];
CH[n-i-1] = temp;
}
}
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;
}
//其中 upbound 编号,HT是哈夫曼树,HC是哈夫曼编码,w是权值,n是叶子节点个数
void SelectTwoMin(int upbound, HuffmanTree HT, int &s1, int &s2)
{
int x1=0,x2=0;
int m1= 1000;
int m2= 1000;
for(int i=1; i<=upbound; i++)
{
if(HT[i].parent == 0&& HT[i].weight < m1)
{
m2= m1;
x2 = x1;
m1 = HT[i].weight;
x1 = i;
}
else if(HT[i].parent == 0 && HT[i].weight <m2)
{
m2 = HT[i].weight;
x2 = i;
}
}
s1 = x1;
s2 = x2;
}
void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n)
{
int s1=0;
int s2=0;
HT = (HuffmanTree)malloc(sizeof(HTNode)*(2*n));
HC = (char **)malloc(sizeof(char *)*(n+1));
for(int i=1;i<=n;i++)
{
HC[i] = (char *)malloc(sizeof(char)*(n+1));
memset(HC[i],0,sizeof(char)*(n+1));
}
for (int i = 0; i <n ; ++i) {
HT[i+1].weight = w[i];
}//给结构体赋值
for(int i=1;i<=2*n-1;i++)
{
HT[i].parent = 0;
HT[i].lchild = 0;
HT[i].rchild = 0;
}
for (int i = 0; i <n-1 ; ++i) {
SelectTwoMin(n+i,HT,s1,s2);
HT[i+n+1].lchild = s1;
HT[i+n+1].rchild = s2;
HT[i+n+1].weight = HT[s1].weight+HT[s2].weight;
HT[s1].parent = i+n+1;
HT[s2].parent = i+n+1;
}
//
for (int i = 1; i <= n ; ++i) {
int c = i;
int parent = HT[c].parent;
while (parent!=0)
{
if(HT[parent].lchild==c)
{
strncat(HC[i],"0",1);
}
else
strncat(HC[i],"1",1);
c = parent;
parent = HT[parent].parent;
}
reverse(HC[i]);
}
}