huffman编码---zoj_1117

huffman编码是一种优化的编码方法,于ASCII等固定长度的编码方法相比较,他可以使编码的长度缩短。其主要的思路是,让出现频率高的字符拥有较短的编码,让出现频率较低的字符,拥有较长的编码。但是,这样的编码方式就要求任意一个字符的编码不能是其他字符编码的前缀,通常这种编码方式叫前缀编码。
         huffman编码通过构造huffmanTree来实现,贪心思想。取权值(频率)最低的2个节点为新节点的左右子节点,新节点的权值为子节点权值之和。处理之后,子节点标记为已经处理过,新节点标记为未处理。循环处理该过程。如果huffmanTree中有m个叶节点,那么huffmanTree中肯定有n=2*m-1个节点。因此,当huffmanTree中有2*m-1个节点时,huffmanTree构造就结束了。

//zoj1117.cpp  
#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
class huffmanNode
{
public:
	int value,parent,left,right,pos;
	bool isset;
	int  dir;
	huffmanNode()
	{
		this->isset=false;
		this->left=-1;
		this->right=-1;	
		this->parent=-1;
		this->pos=-1;
		this->dir=1;
	}
	huffmanNode(int value,int pos):value(value),pos(pos)
	{
		this->isset=false;
		this->left=-1;
		this->right=-1;
		this->parent=-1;
		this->dir=-1;	
	}
};
class huffmanTree
{
public:
	huffmanNode hflist[20000];
	int n,count,flag;
	huffmanTree(int count,int n)
	{
		this->count=count;
		this->n=n;
		this->flag=count;
	}
	void createTree()
	{
		while(flag<n)
		{
			int a=0;
			int b=0;
			int va=99999998;
			int vb=99999999;
			for(int i=0;i<flag;i++)
			{
				if(hflist[i].isset)
				continue;
				if(hflist[i].value<vb)
				{	
					b=i;
					vb=hflist[i].value;
				}
				if(vb<va)
				{
					int temp=vb;
					vb=va;
					va=temp;
					temp=b;
					b=a;
					a=temp;
				}
			}
			huffmanNode node(hflist[a].value+hflist[b].value,flag);
			node.left=a;
			node.right=b;
			hflist[flag]=node;
			hflist[a].parent=flag;
			hflist[a].dir=0;
			hflist[b].dir=1;
			hflist[b].parent=flag;
			hflist[a].isset=true;
			hflist[b].isset=true;
			++flag;
		}	
	}
	int  getEncoding(int n)
	{
		if(n>=count)
			return 0;
		int flag=n;
		int result=0;
		while(hflist[flag].parent!=-1)
		{
			//cout<<hflist[flag].dir<<" ";
			flag=hflist[flag].parent;
			++result;
		}
		return result;
	}

};
int num[27];
int flag,m,n;
int main()
{
	char ch[20000];
	memset(ch,0,sizeof(ch));
	while(scanf("%s",ch)!=EOF)
	{
		//cout<<ch<<endl;
		if(ch[0]=='E'&&ch[1]=='N'&&ch[2]=='D'&&ch[3]=='\0')
		break;
		memset(num,0,sizeof(num));
		flag=0;
		m=0;
		while(ch[flag]!=0)
		{
			if(ch[flag]=='_')
			{
				if(num[26]==0)
				++m;
				++num[26];
			}
			else
			{
				if(num[ch[flag]-65]==0)
				++m;
				++num[ch[flag]-65];
			}
			++flag;
		}
		n=m*2-1;
		int j=0;
		huffmanTree tree(m,n);
		for(int i=0;i<27;i++)
		{
			if(i!=26&&num[i]>0)
			{
				huffmanNode node(num[i],j);
				tree.hflist[j]=node;
				j++;
			}
			if(i==26)
			{
				huffmanNode node(num[26],j);
				tree.hflist[j]=node;
				j++;	
			}
			
		}
		/*for(int i=0;i<m;i++)
		{
			cout<<tree.hflist[i].value<<endl;
		}*/
		cout<<flag*8<<" ";
		tree.createTree();
		int result=0;
		if(m<=1)
		result=tree.hflist[0].value;
		else
		{
			for(int i=0;i<m;i++)
			{
			result+=tree.getEncoding(i)*tree.hflist[i].value;
			//cout<<endl;		
			}
		}
		cout<<result<<" ";
		printf("%.1f\n",(float)8*flag/result);
		memset(ch,0,sizeof(ch));
	}

	
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值