那些年我写的哈夫曼树(i love you.)

/*一级指针要改*/
#include "stdio.h"
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#define MAXVALUE 1000
#define MAXSIZE 29
#define MAXBIT 10
typedef struct hnode
{
	int weight,parent,lchild,rchild;
}hnode,*htree;
typedef char *hcode;
void huffmancoding(hnode *ht,hcode **hc,int *w,int n)/*hcode是三级指针*/
{
	int m,m1,m2,x1,x2,i,j,start,c,f;/*hc本来应该存字符串,一级指针,所以HC在主函数中应为二级指针,但要传递的是数据*/
	char *cd;						/*所以应把二级指针的地址给形参,及形参应为三级指针*/
	hnode *p;						/*同理HT在形参中应作为HNODE的地址,及一级指针*/
	if(n<=1) return;				/*值传递传的是原值的一个拷贝,不能使原值发生任何变化*/
	m=2*n-1;						/*要使原值变化,应传递引用方式(int &a,int &b)或传址方式(&a,&b)*/
	ht=(hnode *)malloc(m*sizeof(hnode));/*而PRINT函数不一样它做的是输出,既能用传值也可传址,或引用方式,因为不需要对原值产生变化*/
	for(p=ht,i=0;i<n;++i,++p,++w)
	{
		p->weight=*w;p->lchild=-1;
		p->rchild=-1;p->parent=-1;
	}
	for(;i<m;++i,++p)
	{
		p->weight=0;p->lchild=-1;
		p->rchild=-1;p->parent=-1;
	}
	for(i=n;i<m;++i)/*构造哈弗曼树*/
	{
		m1=m2=MAXVALUE;
		x1=x2=0;
		for(j=0;j<i;++j)
		{
			if(ht[j].parent==-1&&ht[j].weight<m1)
			{
				m2=m1;x2=x1;m1=ht[j].weight;x1=j;
			}
			else if(ht[j].parent==-1&&ht[j].weight<m2)
			{
				m2=ht[j].weight;x2=j;
			}
		}
		ht[x1].parent=i;ht[x2].parent=i;
		ht[i].lchild=x1;ht[i].rchild=x2;
		ht[i].weight=m1+m2;
	}
	/*字符编码*/
	*hc=(hcode *)malloc(n*sizeof(hcode));
	cd=(char *)malloc(n*sizeof(char));
	cd[n-1]='\0';
	for(i=0;i<n;++i)
	{
		start=n-1;
		for(c=i,f=ht[i].parent;f!=-1;c=f,f=ht[f].parent)
		if(ht[f].lchild==c)
		   cd[--start]='0';
		else cd[--start]='1';
		(*hc)[i]=(char *)malloc((n-start)*sizeof(char));
		strcpy((*hc)[i],&cd[start]);
	}
	free(cd);
}
int count(char *s,int cnt[],char str[])
{
	char *p;
	int i,j,k;
	int temp[29];
	for(i=0;i<29;i++) temp[i]=0;
	for(p=s; *p!='\0';p++)
	{
		if(*p>='a'&& *p<='z')
		{
			k=(*p)-97;
			temp[k]++;
		}
		else if(*p==',')
		{
			k=(*p)-18;
			temp[k]++;
		}
		else if(*p=='.')
		{
			k=(*p)-19;
			temp[k]++;
		}
		else if(*p==' ')
		{
			k=(*p)-4;
			temp[k]++;
		}
	}
	for(i=0,j=0;i<29;i++)
	{
		if(temp[i]!=0)
		{
			if(i<26)
			{
				str[j]=i+97;
				cnt[j]=temp[i];
				j++;
			}
			else if(i==26)
			{
				str[j]=i+18;
				cnt[j]=temp[i];
				j++;
			}
			else if(i==27)
			{
				str[j]=i+19;
				cnt[j]=temp[i];
				j++;
			}
			else if(i==28)
			{
				str[j]=i+4;
				cnt[j]=temp[i];
				j++;
			}
		}
	}
	str[j]='\0';
	return j;
}
void print(hcode *hc,char str[],int n)
{
	int i;
	for(i=0;i<n;i++)
	{
		printf("  %c->: ",str[i]);
		puts(hc[i]);
		putchar('\n');
	}
	return;
}
void coding(hcode **hc,char *s,char str[])
{
	int i,j;
	char *cp;
	FILE *fp;
	fp=fopen("d:\\codefile.txt","w");
	while(*s)
	{
		for(i=0;i<MAXSIZE;i++)
		if(str[i]==*s)
		{
			for(j=0,cp=(*hc)[i];j<(int)strlen((*hc)[i]);j++,cp++)
			fputc(*cp,fp);
			break;
		}
		s++;
	}
	fclose(fp);
}
char *decode(hcode **hc,char str[],int num)
{
	FILE *fp;
	char s[254];
	char *p;
	static char cd[MAXBIT+1];
	int i,j,k=0,cjs;
	fp=fopen("d:\\codefile.txt","r");
	while(!feof(fp))
	{
		cjs=0;
		for(i=0;i<MAXSIZE&&cjs==0&&!feof(fp);i++)
		{
			cd[i]=' ';cd[i+1]='\0';
			cd[i]=fgetc(fp);
			for(j=0;j<num;j++)
			if(strcmp((*hc)[j],cd)==0)
			{
				s[k]=str[j];
				k++;
				cjs=1;
				break;
			}
		}
	}
	s[k]='\0';
	p=s;
	return p;
}
void main()
{
	char st[254],*s,str[29];
	int cn[29],num;
	hnode ht;
	hcode *hc;
	printf("input the setense:\n");
	gets(st);
	num=count(st,cn,str);
	huffmancoding(&ht,&hc,cn,num);
	print(hc,str,num);
	coding(&hc,st,str);
	s=decode(&hc,str,num);
	printf("%s\n",s);
}
		
		

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值