#define M 1000
#define N 128
typedef struct node
{
int weight;
struct node *lchild , *rchild , *parent ;
struct node *next;
}HuffmanNode , *HuffmanTree;
typedef struct
{
char ch;
char code[N];
}CodeNode;
int n;
void Open(char s[])
{
FILE *fp;
char name[10];
int i=0;
printf("请输入你要打开的文件名:");
gets(name);
if ((fp = fopen(name,"rt")) == NULL )
{
printf("打开文件失败!/n");
exit(1);
}
s[i++] = fgetc(fp);
while(s[i-1] != EOF)
s[i++] = fgetc(fp);
s[i] = '/0';
printf("读取到的字符:/n");
puts(s);
fclose(fp);
}
void Save(char s[])
{
FILE *fp;
char name[10];
printf("请输入你要保存的文件名:");
gets(name);
if ((fp = fopen(name,"wt")) == NULL)
{
printf("保存文件失败!/n");
exit(1);
}
fputs(s,fp);
fclose(fp);
}
void SearchStr(char s[] , char str[] , int count[])
{
int i , j , k=0;
for (i=0 ; i<N ; i++)
count[i] = 0;
for (i=0 ; s[i] ; i++)
{
for (j=0 ; j<k ; j++)
{
if (str[j] == s[i])
{
count[j]++;
break;
}
}
if (j == k)
{
str[k] = s[i];
count[k]++;
k++;
}
}
str[k-1] = '/0';
n = k-1;
}
void SelectMin(HuffmanTree HT , int k , HuffmanTree *HT1 , HuffmanTree *HT2)
{
int i , min;
HuffmanTree p;
min = 3128;
for ( p=HT,i=0 ; i<k ; i++,p=p->next)
{
if (p->weight<min && p->parent == NULL)
{
min = p->weight;
*HT1 = p ;
}
}
min = 3128;
for ( p=HT,i=0 ; i<k ; i++,p=p->next)
{
if (p->weight<min && p->parent == NULL && p!=*HT1)
{
min = p->weight;
*HT2 = p ;
}
}
}
void CreatHuffmanTree(HuffmanTree *HT , int count[])
{
int i;
HuffmanTree p , HT1 , HT2;
p = *HT = (HuffmanTree)malloc(sizeof(HuffmanNode));
p->next = p->lchild = p->rchild = p->parent = NULL;
for (i=0 ; i<2*n-1 ; i++)
{
p->next = (HuffmanTree)malloc(sizeof(HuffmanNode));
p = p->next;
p->next = p->lchild = p->rchild = p->parent = NULL;
}
for ( p=*HT ,i=0 ; i<n ; i++)
{
p->weight = count[i];
p = p->next;
}
for (i=n ; i<2*n-1 ; i++)
{
SelectMin(*HT,i,&HT1,&HT2);
HT1->parent = HT2->parent = p;
p->lchild = HT1;
p->rchild = HT2;
p->weight = HT1->weight + HT2->weight;
p = p->next;
}
free(p);
}
void CodeHuffman(HuffmanTree HT , CodeNode HC[] , char str[])
{
int i , j , k , x;
char ch;
HuffmanTree p , q=HT;
for (i=0 ; i<n ; i++)
HC[i].ch = str[i];
for (i=0 ; i<n ; i++)
{
j = 0;
x = 0;
for ( p=q; p->parent ; p=p->parent)
{
if (p == p->parent->lchild)
HC[i].code[j++] = '0';
else
HC[i].code[j++] = '1';
}
HC[i].code[j] = '/0';
k = j/2;
while(j>k) //编码反转
{
ch = HC[i].code[j-1];
HC[i].code[j-1] = HC[i].code[x];
HC[i].code[x] = ch ;
j--;
x++;
}
q = q->next;
}
}
void ToltalCoding(CodeNode HC[] , char s[] , char code[])
{
int i , j ;
code[0] = '/0';
for (i=0 ; s[i] ; i++)
{
for (j=0 ; j<n ; j++)
{
if (s[i] == HC[j].ch)
strcpy(code+strlen(code),HC[j].code);
}
}
}
void Decoding(HuffmanTree HT , char code[] , char str[] , char ss[])
{
int i , j , k=0 ;
HuffmanTree p , q , root;
for (root=HT ; root->parent ; root=root->parent);
for (i=0 , p=root ; code[i] ; i++)
{
if (code[i] == '0')
p = p->lchild;
else
p = p->rchild;
if (p->lchild==NULL && p->rchild==NULL)
{
for (j=0,q=HT ; q!=p ; q=q->next,j++);
ss[k++] = str[j];
p = root;
}
}
ss[k] = '/0';
printf("解码结果:/n");
puts(ss);
}
void main(void)
{
int i = 0;
// char xuanzhe;
char s[M],ss[M]; //定义字符串数组,s[]存放将要编码的字符串,ss[]存解码后的字符串
char str[N]; //存放输入的字符串中n个不同的字符
int count[N]; //存放n个不同字符对应的在原字符串中出现的次数
char code[M]; //存放最终编码完成后的编码
// char choice;
HuffmanTree HT; //定义一个哈夫曼树的链表
CodeNode HC[N];
Open(s);
SearchStr(s,str,count);
CreatHuffmanTree(&HT,count);
CodeHuffman(HT,HC,str);
for ( i=0 ; i<n ; i++ )
printf("字符:%c/t权值:%d/t编码:%s/n",str[i],count[i],HC[i].code);
ToltalCoding(HC,s,code);
Decoding(HT,code,str,ss);
free(HT);
}