砝码称重
问题描述
我的代码:
运行结果:
运行结果:
你没有f[0][0]=True那一行,下面的循环又调用了f[i-1]访问出错了
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int ELEMTYPE;
static int m = 0;
int tempa[27] ;
int tempb[27];
char tempc[27];
// 哈夫曼树结点结构体
typedef struct HuffmanTree
{
ELEMTYPE weight;
char letter;
ELEMTYPE id; // id用来主要用以区分权值相同的结点,这里代表了下标
struct HuffmanTree* lchild;
struct HuffmanTree* rchild;
}HuffmanNode;
// 构建哈夫曼树
HuffmanNode* createHuffmanTree(int a[], int n, char b[])
{
int i, j;
HuffmanNode **temp, *hufmTree;
temp = (HuffmanNode**)malloc(n*sizeof(HuffmanNode));
for (i = 0; i<n; ++i) // 将数组a中的权值赋给结点中的weight
{
temp[i] = (HuffmanNode*)malloc(sizeof(HuffmanNode));
temp[i]->weight = a[i];
temp[i]->letter = b[i];
temp[i]->id = i;
temp[i]->lchild = temp[i]->rchild = NULL;
}
for (i = 0; i<n - 1; ++i) // 构建哈夫曼树需要n-1合并
{
int small1 = -1, small2; // small1、small2分别作为最小和次小权值的下标
for (j = 0; j<n; ++j) // 先将最小的两个下标赋给small1、small2(注意:对应权值未必最小)
{
if (temp[j] != NULL && small1 == -1)
{
small1 = j;
continue;
}
else if (temp[j] != NULL)
{
small2 = j;
break;
}
}
for (j = small2; j<n; ++j) // 比较权值,挪动small1和small2使之分别成为最小和次小权值的下标
{
if (temp[j] != NULL)
{
if (temp[j]->weight < temp[small1]->weight)
{
small2 = small1;
small1 = j;
}
else if (temp[j]->weight < temp[small2]->weight)
{
small2 = j;
}
}
}
hufmTree = (HuffmanNode*)malloc(sizeof(HuffmanNode));
hufmTree->weight = temp[small1]->weight + temp[small2]->weight;
hufmTree->lchild = temp[small1];
hufmTree->rchild = temp[small2];
temp[small1] = hufmTree;
temp[small2] = NULL;
}
free(temp);
return hufmTree;
}
// 以广义表的形式打印哈夫曼树
void PrintHuffmanTree(HuffmanNode* hufmTree)
{
if (hufmTree)
{
printf("%d", hufmTree->weight);
if (hufmTree->lchild != NULL || hufmTree->rchild != NULL)
{
printf("(");
PrintHuffmanTree(hufmTree->lchild);
printf(",");
PrintHuffmanTree(hufmTree->rchild);
printf(")");
}
}
}
// 递归进行哈夫曼编码
void HuffmanCode(HuffmanNode* hufmTree, int depth) // depth是哈夫曼树的深度
{
static int code[100];
if (hufmTree)
{
if (hufmTree->lchild == NULL && hufmTree->rchild == NULL)
{
printf("字符为:%c 权值为:%d 哈夫曼编码为: ", hufmTree->letter, hufmTree->weight);
tempc[m] = hufmTree->letter;
//tempb[m] = hufmTree->weight;
int i;
for (i = 0; i<depth; ++i)
{
printf("%d", code[i]);
}printf(" ");
// printf("权重:%d", hufmTree->weight * depth);
tempb[m] = hufmTree->weight * depth;
tempa[m] = depth ;
m ++;
printf("\n");
}
else
{
code[depth] = 0;
HuffmanCode(hufmTree->lchild, depth + 1);
code[depth] = 1;
HuffmanCode(hufmTree->rchild, depth + 1);
}
}
}
// 哈夫曼解码
void HuffmanDecode(char ch[], HuffmanNode* hufmTree, char string[]) // ch是要解码的01串,string是结点对应的字符
{
int i;
int num[500];
HuffmanNode* tempTree = NULL;
for (i = 0; i<strlen(ch); ++i)
{
if (ch[i] == '0')
num[i] = 0;
else
num[i] = 1;
}
if (hufmTree)
{
i = 0; // 计数已解码01串的长度
while (i<strlen(ch))
{
tempTree = hufmTree;
while (tempTree->lchild != NULL && tempTree->rchild != NULL)
{
if (num[i] == 0)
{
tempTree = tempTree->lchild;
}
else
{
tempTree = tempTree->rchild;
}
++i;
}
printf("%c", string[tempTree->id]); // 输出解码后对应结点的字符
}
}
}
int main()
{
int i, n;
int sum = 0;
char str[] = "THIS PROGRAM IS MY FAVORITE";
printf("请输入叶子结点的个数:\n");
while (1)
{
scanf("%d", &n);
if (n>1)
break;
else
printf("输入错误,请重新输入n值!");
}
int* arr;
arr = (int*)malloc(n*sizeof(ELEMTYPE));
printf("请输入%d个叶子结点的权值:\n", n);
for (i = 0; i<n; ++i)
{
scanf("%d", &arr[i]);
}
char ch[500], string[500];
printf("请连续输入这%d个叶子结点各自所代表的字符:\n", n);
fflush(stdin); // 强行清除缓存中的数据,也就是上面输入权值结束时的回车符
gets(string);
HuffmanNode* hufmTree = NULL;
hufmTree = createHuffmanTree(arr, n, string);
printf("此哈夫曼树的广义表形式为:\n");
PrintHuffmanTree(hufmTree);
printf("\n各叶子结点的哈夫曼编码为:\n");
HuffmanCode(hufmTree, 0);
for(i = 0;i <27; i ++){
printf("字符:%c 权值:%d 报文:%d", tempc[i], tempb[i], tempa[i]);
printf("\n");
}
for (i = 0;i < 27; i++) {
switch (str[i])
{
case 'C':
sum += tempa[0];break;
case 'U':
sum += tempa[1];break;
case 'H':
sum += tempa[2];break;
case 'R':
sum += tempa[3];break;
case 'S':
sum += tempa[4];break;
case 'E':
sum += tempa[5];break;
case 'I':
sum += tempa[6];break;
case 'N':
sum += tempa[7];break;
case 'B':
sum += tempa[8];break;
case 'G':
sum += tempa[9];break;
case 'P':
sum += tempa[10];break;
case 'Y':
sum += tempa[11];break;
case 'O':
sum += tempa[12];break;
case 'A':
sum += tempa[13];break;
case 'D':
sum += tempa[14];break;
case 'L':
sum += tempa[15];break;
case 'V':
sum += tempa[16];break;
case 'J':
sum += tempa[17];break;
case 'Q':
sum += tempa[18];break;
case 'X':
sum += tempa[19];break;
case 'Z':
sum += tempa[20];break;
case 'K':
sum += tempa[21];break;
case 'W':
sum += tempa[22];break;
case 'M':
sum += tempa[23];break;
case 'F':
sum += tempa[24];break;
case 'T':
sum += tempa[25];break;
case ' ':
sum += tempa[26];break;
default:
sum = 0;
break;
}
}
printf("THIS PROGRAM IS MY FAVORITE的公文长度为:%d", sum);
printf("\n");
printf("要解码吗?请输入编码:\n");
gets(ch);
printf("解码结果为:\n");
HuffmanDecode(ch, hufmTree, string);
printf("\n");
free(arr);
free(hufmTree);
return 0;
}