哈夫曼编码

#include<malloc.h>
#include<stdio.h>
#include<string.h>
#define MAX 100
typedef struct
{
	int weight;
	int parent,lchild,rchild;
	char c1;//用于接收来自链表的字符 
}HTNode,*HuffmanCode;
typedef struct
{
	char cd[MAX];
	int start;
}HCode;
typedef struct node
{
	char ch;//表示字符串中的字符
	int count;//表示每个字符的频度 
	int n;
	struct node *next;
}linknode,*linklist;

void  character_count(char *str,linklist *L);
void print(linklist L);
int count(linklist L);
void sort(linklist *L);//对字符按权值大小进行升序排列 
void Insert(linklist *L,int weight1,int n1);
void Create_HuffmanTree(HuffmanCode *HT,linklist *L);
void HuffmanCoding(HuffmanCode HT,HCode *hcd,int n,char *str);
void IPT();
#include"huffman.h"
void  character_count(char *str,linklist *L)
{
	int n[26]={0};//26个位置对应存放26个字母的频度
	char c[26]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
	'r','s','t','u','v','w','x','y','z'};
	int i=0,j=1;
	for(i=0;i<strlen(str);i++)//对字符串内字符进行遍历统计 
	{
		switch(str[i])
		{
			case 'a':n[0]++;break;
			case 'b':n[1]++;break;
			case 'c':n[2]++;break;
			case 'd':n[3]++;break;
			case 'e':n[4]++;break;
			case 'f':n[5]++;break;
			case 'g':n[6]++;break;
			case 'h':n[7]++;break;
			case 'i':n[8]++;break;
			case 'j':n[9]++;break;
			case 'k':n[10]++;break;
			case 'l':n[11]++;break;
			case 'm':n[12]++;break;
			case 'n':n[13]++;break;
			case 'o':n[14]++;break;
			case 'p':n[15]++;break;
			case 'q':n[16]++;break;
			case 'r':n[17]++;break;
			case 's':n[18]++;break;
			case 't':n[19]++;break;
			case 'u':n[20]++;break;
			case 'v':n[21]++;break;
			case 'w':n[22]++;break;
			case 'x':n[23]++;break;
			case 'y':n[24]++;break;
			case 'z':n[25]++;break;
		} 
	}
	(*L)=(linklist)malloc(sizeof(linknode));
	linklist p,q;
	//p=(linlist)malloc(sizeof(linknode));
	p=*L;//使用尾插法存储字符 
	for(i=0,j=1;i<26;i++)
	{
		if(n[i]!=0)
		{
			q=(linklist)malloc(sizeof(linknode));
			q->n=j++;
			q->ch=c[i];
			q->count=n[i];
			p->next=q;
			p=q;
		}
	}
	p->next=NULL;
}
void print(linklist L)
{
	linklist p=L->next;
	while(p)
	{
		//printf("%d ",p->count);
		printf("%c:%d ",p->ch,p->count);
		p=p->next;
	}
}
int count(linklist L)
{
	linklist p=L->next;
	int num=0;
	while(p)
	{
		num++;
		p=p->next;	
	}
	return num;
}
void sort(linklist *L)//对字符按权值大小进行升序排列 
{
	linklist p,q,r;
	int i=0;
	i=count(*L);
	while(i-->0) 
	{//进行结点数次内层循环 
	//仿照冒泡排序法对字符按照权值进行升序排列 
		p=*L;
		while(p->next->next)//当p指向倒数第三个结点时该层遍历结束 
		{//该层每次循环把一个最大值推至最右边 
			q=p->next; r=q->next;
			if(q->count>r->count)
			{
				q->next=r->next;
				p->next=r;
				r->next=q;
			}
			p=p->next;
		}
	}
}
void Insert(linklist *L,int weight1,int n1)
{
	linklist p;
	p=(linklist)malloc(sizeof(linknode));
	p->n=n1;
	p->ch='*';//合成的结点插入进来字符为除26个小写字母之外的字符 
	p->count=weight1;
	p->next=(*L)->next;
	(*L)->next=p;
}

/********************************************/
void Create_HuffmanTree(HuffmanCode *HT,linklist *L)
{
	int n=count(*L);
	int m=0;
	int i=0;
	linklist p,q,r;
	HuffmanCode T; 
	p=(linklist)malloc(sizeof(linknode));
	//m=2*n-1;//无效??? 
	(*HT)=(HuffmanCode)malloc((2*n)*sizeof(HTNode));
	p=(*L)->next;//设置链表指针,取出链表中的字符及权值进行构造树
	for(i=1;i<=n&&p;++i)//对前n个叶子结点进行初始化 
	{
		(*HT)[i].c1=p->ch;
		(*HT)[i].weight=p->count;
		//printf("%d\n",(*HT)[i].weight);
		(*HT)[i].parent=0;
		(*HT)[i].lchild=0;		
		(*HT)[i].rchild=0; 
		 p=p->next;
	} 
	m=2*n-1;
	for(i=n+1;i<=m;++i)//对后n-1个合成结点进行初始化 
	{
		(*HT)[i].c1='*';
		(*HT)[i].weight=0;
		(*HT)[i].parent=0;
		(*HT)[i].lchild=0;		
		(*HT)[i].rchild=0;
	}
	for(i=n+1;i<=m;i++)
	{
		sort(L);//经过升序排列后,链表前两个结点的权值最小 
		q=(*L)->next;
		r=q->next;
		//printf("%d %d\n",q->n,r->n);
		(*HT)[q->n].parent=i;
		(*HT)[r->n].parent=i;
		(*HT)[i].lchild=q->n;
		(*HT)[i].rchild=r->n;
		(*HT)[i].weight=(*HT)[q->n].weight+(*HT)[r->n].weight;
		(*L)->next=r->next;
		//按照哈夫曼树构成规则,将最小的两个结点删去 
		free(q);
		free(r);
		//printf("%d\n",(*HT)[i].weight);
		Insert(L,(*HT)[i].weight,i);				
	}
	for(i=1;i<=m;i++)
	{
		printf("%d %d %d %d %d",i,(*HT)[i].weight,(*HT)[i].parent,(*HT)[i].lchild,(*HT)[i].rchild);
		printf("\n");
	}
}

void HuffmanCoding(HuffmanCode HT,HCode *hcd,int n,char *str)
{
	HCode hc;
	int i=0,c=0,f=0,j=0,m=0;
	for(i=1;i<=n;i++)
	{
		hc.start=n-1;
		c=i;
		f=HT[i].parent;
		//printf("%d\n",f);
		while(f!=0)
		{
			if(HT[f].lchild==c)
				hc.cd[hc.start--]='0';
			else
				hc.cd[hc.start--]='1';
			c=f;
			f=HT[f].parent;		
		}
		hc.start++;
		hcd[i]=hc;
		
	}
	for(i=1;i<=n;i++)
	{
		printf("%c: ",HT[i].c1);
		for(j=hcd[i].start;j<=n-1;j++)
		printf("%c",hcd[i].cd[j]);
		printf("  ");
	 }
	 printf("\n");
	 for(j=0;j<strlen(str);j++)
	 {
	 	for(i=1;i<=n;i++)
	 	{
	 		if(str[j]==HT[i].c1)
	 		break;
		}
		for(m=hcd[i].start;m<=n-1;m++)
		printf("%c",hcd[i].cd[m]);
	 }
}





#include"huffman.h"
void IPT()
{
	char a[100]={'0'};
	linklist L;
	L=(linklist)malloc(sizeof(linknode));
	HuffmanCode HT;
	int n=0;
	while(1)//判断是否结束运行 
	{	
	scanf("%s",a);
	if(!strcmp(a,"0"))
	break;
	character_count(a,&L);
	print(L); 
	if(count(L)==1)//对于只有一种字符的字符串编码进行特殊处理 
	{
		printf("\n");
		printf("1 %d 0 0 0\n",strlen(a)); 
		printf("编码为1\n");
	}
	else
	{
		n=count(L);
		HCode hcd[n+1];
		printf("\n");
		Create_HuffmanTree(&HT, &L);
		HuffmanCoding(HT,hcd,n,a);
		printf("\n");
	}
	printf("%s\n",a);
	}
}
#include"huffman.h"
int main()
{
	IPT();
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值