赫夫曼编码

/* 
   功能Function Description:     赫夫曼编码---正误待验证(调试时候感觉有地方好像出错了)
   开发环境Environment:          DEV C++ 4.9.9.1
   技术特点Technique:
   版本Version:
   作者Author:                   可笑痴狂
   日期Date:                 	 20120803
   备注Notes:                  
   作用:
		输入大写字母组成的字符串,然后以其出现的次数为权重进行编码
*/
#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;

typedef struct Node
{
	unsigned int weight;
	unsigned int parent,left,right;
}HTNode,*HuffmanTree;
typedef char **HuffmanCode;

void HuffmanCoding(int *w,int n,char *s)
{
	HuffmanTree HT;
	HuffmanCode HC;
	HuffmanTree p;
	int m,i,j,s1,s2,min1,min2,c,f,start;
	if(n<1)
		return;
	m=2*n-1;
	HT=new HTNode[m+1];           //0号单元没用

	for(p=HT+1,i=1;i<=n;++i,++p,++w)      //初始化
	{
		p->weight=*w;
		p->parent=0;
		p->left=0;
		p->right=0;
	}
	for(;i<=m;++i,++p)
	{
		p->weight=0;
		p->parent=0;
		p->left=0;
		p->right=0;
	}
	for(i=n+1;i<=m;++i)
	{
		min1=min2=0x7fffffff;
		//在HT[1,2,.....i-1]中选择parent为0且weight值最小的两个结点,其序号分别为s1、s2
		for(j=1;j<i;++j)
		{
			if(HT[j].parent==0&&min1>HT[j].weight)
			{
				min1=HT[j].weight;
				s1=j;
			}
		}
		HT[s1].parent=i;
		for(j=1;j<i;++j)
		{
			if(HT[j].parent==0&&min2>HT[j].weight)
			{
				min2=HT[j].weight;
				s2=j;
			}
		}
		HT[s2].parent=i;
		HT[i].left=s1;
		HT[i].right=s2;
		HT[i].weight=HT[s1].weight+HT[s2].weight;
	}

	//从叶子节点到根逆向求每个字符的赫夫曼编码
	HC=new char*[n+1];     //分配n个字符编码的头指针向量
    char* cd=new char[n];            //分配求编码的工作空间
	cd[n-1]='\0';
	for(i=1;i<=n;++i)          //逐个字符求其编码
	{
		start=n-1;         //编码结束符标志
		for(c=i,f=HT[i].parent;f;c=f,f=HT[f].parent) //从叶子到根逆向求编码
			if(HT[f].left==c)
				cd[--start]='0';
			else
				cd[--start]='1';
		HC[i]=new char[n-start];
		strcpy(HC[i],&cd[start]);
	}
	delete cd;
	for(i=0;i<n;++i)       //输出编码
		cout<<s[i]<<": "<<HC[i+1]<<endl;
}

int main()
{
	char s[1000];
	int i,j;
	int weight[27];
	/*
	HuffmanTree HT;
	HuffmanCode HC;
	*/
	cout<<"请输入字符串(大写字母):"<<endl;
	while(cin>>s)
	{
		memset(weight,0,sizeof(weight));
		int len=strlen(s);
		for(i=0;i<len;++i)
			++weight[s[i]-'A'];
		for(i=0,j=0;i<26;++i)    //去掉没有出现过的字母,将字母和权值都压缩存储到原来的空间中
			if(weight[i])
			{
				s[j]=i+'A';
				weight[j++]=weight[i];
			}
		cout<<"赫夫曼编码为:"<<endl;
		HuffmanCoding(weight,j,s);
		cout<<"请输入字符串(大写字母):"<<endl;
	}
	return 0;
}

 

你可能感兴趣的:(编码)