哈夫曼编码问题

#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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值