#include<stdio.h>
#include<stdlib.h>
#include<strings.h>
typedef struct{
char ch;
unsigned int weight;
}Letter;
typedef struct{
unsigned int weight;
unsigned int parent,lchild,rchild;
}HTNode,*HuffmanTree;
typedef char **HuffmanCode;
typedef struct BiTNode{
char ch;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
BiTree Create_BiTNode(char ch){
BiTree node=(BiTree)malloc(sizeof(BiTNode));
node->lchild=node->rchild=NULL;
node->ch=ch;
return node;
}
//统计词频
void CountingLetterFrequencies(char str[],int cnt[],int *n){
int i=0,count=0,j=0;
for(i=0;i<strlen(str);i++)cnt[str[i]-'a']++;
for(i=0;i<26;i++)cnt[i]>0?printf("%c:%d ",'a'+i,cnt[i]):count++;
*n=26-count;
}
// 选择权值最小的两个节点
void Select(HuffmanTree HT,int i,int *s1,int *s2){
int j=0,min,secondMin,weight,secondWeight;
weight=secondWeight=INT_MAX;
min=secondMin=0;
for(j=1;j<i;j++){
if(!HT[j].parent){
if(HT[j].weight<weight){
secondWeight=weight;
weight=HT[j].weight;
secondMin=min;
min=j;
}
else if(HT[j].weight<secondWeight){
secondMin=j;
}
}
}
*s1=min;
*s2=secondMin;
}
// 创建哈夫曼树
HuffmanTree Create_HuffmanTree(Letter letter[],int n){
if(n<=1)return NULL;
HuffmanTree HT=NULL;
int m=2*n-1,i;
HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
for(i=1;i<=n;i++){
HT[i].weight=letter[i-1].weight;
HT[i].parent=HT[i].lchild=HT[i].rchild=0;
}
for(;i<=m;i++)HT[i].weight=HT[i].parent=HT[i].lchild=HT[i].rchild=0;
for(i=n+1;i<=m;i++){
int s1,s2;
Select(HT,i,&s1,&s2);
// printf("\n%d %d",s1,s2);
HT[s1].parent=HT[s2].parent=i;
HT[i].weight=HT[s1].weight+HT[s2].weight;
HT[i].lchild=s1;HT[i].rchild=s2;
}
for(i=1;i<=m;i++)printf("\n%d %d %d %d %d",i,HT[i].weight,HT[i].parent,HT[i].lchild,HT[i].rchild);
return HT;
}
//字符串倒序
void reverseString(char str[]) {
int length = strlen(str);
int start = 0;
int end = length - 1;
while (start < end) {
// 交换字符
char temp = str[start];
str[start] = str[end];
str[end] = temp;
// 移动指针
start++;
end--;
}
}
// 哈夫曼编码
void HuffmanCoding(HuffmanTree HT,int n,HuffmanCode Codes,Letter letter[]){
int i,j,c,f;
// *Codes=(HuffmanCode)malloc(n*sizeof(char*));
for(i=1;i<=n;i++){
char *str=(char*)malloc(n*sizeof(char));
j=0;
for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent){
if(HT[f].lchild==c) str[j++]='0';
else str[j++]='1';
}
str[j]='\0';
reverseString(str);
Codes[i-1]=str;
}
printf("\n");
for(i=0;i<n;i++){
printf("%c:%s ",letter[i].ch,Codes[i]);
}
}
//编码
void Coding(char str[],Letter letter[],HuffmanCode Codes,int n,char Coding_string[]){
int i,j;
printf("\n");
for(i=0;str[i];i++){
j=0;
while(str[i]!=letter[j].ch)j++;
if(j<n)strcat(Coding_string,Codes[j]);
}
printf("%s\n",Coding_string);
}
// 根据前缀编码构建哈夫曼树的函数
BiTree buildHuffmanTree(Letter letter[],HuffmanCode Codes, int n) {
BiTree T = Create_BiTNode('\0'); // 创建根节点
int i,j;
for (i = 0; i < n; i++) {
BiTree current = T;
char *str = Codes[i];
char ch = letter[i].ch;
for (j = 0; j < strlen(str); j++) {
if (str[j] == '0') {
if (current->lchild == NULL) {
current->lchild = Create_BiTNode('\0');
}
current = current->lchild;
} else if (str[j] == '1') {
if (current->rchild == NULL) {
current->rchild = Create_BiTNode('\0');
}
current = current->rchild;
}
}
// 在叶子节点处存储字符
current->ch = ch;
}
return T;
}
// 解码函数
void Decoding(BiTree T, char Coding_string[]) {
BiTree current = T;
int i,j=0;
char str[100];
for (i = 0; i < strlen(Coding_string); i++) {
if (Coding_string[i] == '0') {
current = current->lchild;
} else if (Coding_string[i] == '1') {
current = current->rchild;
}
if (current->lchild == NULL && current->rchild == NULL) {
str[j++]=current->ch;// 叶子节点
current = T; // 重置为根节点,继续下一个字符的解码
}
}
str[j]='\0';
printf("%s\n\n",str);
}
int main(){
char str[1000];
gets(str);
while(str[0]!='0'){
int cnt[26]={0},n=0,i=0,j=0;
char Coding_string[1000]={'\0'};
CountingLetterFrequencies(str,cnt,&n);
Letter letter[n];
for(i=0;i<26;i++){
if(cnt[i]>0){
letter[j].ch='a'+i;
letter[j++].weight=cnt[i];
}
}
HuffmanTree HT=Create_HuffmanTree(letter,n);
HuffmanCode Codes=(HuffmanCode)malloc(n*sizeof(char*));
HuffmanCoding(HT,n,Codes,letter);
Coding(str,letter,Codes,n,Coding_string);
BiTree T=buildHuffmanTree(letter,Codes,n);
Decoding(T,Coding_string);
gets(str);
}
return 0;
}
哈夫曼编码问题
最新推荐文章于 2024-10-10 22:59:02 发布