实验4-哈夫曼编码实现电文压缩存储

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#define M 1000
using namespace std;
//哈夫曼树
typedef struct
{
	char ch;
	int weight;
	int parent,lc,rc;
}HNode,*HuffmanTree;

//哈夫曼编码
typedef char **HuffmanCode; 

struct Rule {
	bool operator()(const char& a1,const char& a2)const {
		int a=(int)a1,b=(int)a2;
		return a<b;
	}
};
 
void select(HuffmanTree &HT,int n,int &s1,int &s2);
void CreateHuff(HuffmanTree &HT,int *w,char *c,int n);
void CreateHuffmanCode(HuffmanTree HT,HuffmanCode &HC,int n);
void mySort(string str,char *node,int *w,int n);
//select函数
void select(HuffmanTree &HT,int n,int &s1,int &s2)//s1,s2为最小权重,分别作为i的左右孩子 
{
	int minum;
	for(int i=1;i<=n;i++)//寻找第一个最小值 
	{
		if(HT[i].parent==0)
		{
			minum=i;
			break;
		}
	}
	for(int i=1;i<=n;i++)
	{
		if(HT[i].parent==0)
		{
			if(HT[i].weight<HT[minum].weight)
			{
				minum=i;
			}
		}
	 }
	 s1=minum; 

 //寻找第二个最小值,并且与第一个不同 
    for(int i=1;i<=n;i++)
	{
		if(HT[i].parent==0&&i!=s1)
		{
			minum=i;
			break;
		}
	 }
	 for(int i=1;i<=n;i++)
	{
		if(HT[i].parent==0&&i!=s1)
		{
			if(HT[i].weight<HT[minum].weight)
			{
				minum=i;
			}
		}
	 }
	 s2=minum;
}
//创建哈夫曼树 
void CreateHuff(HuffmanTree &HT,int *w,char *c,int n)
{
	int m,s1,s2;
	m=2*n-1;
	HT=new HNode[m+1];//分配空间
	for(int i=1;i<=n;i++)//1-n放叶子节点,还有(n-1)个存储空间放产生的新节点 
	{
		HT[i].weight=w[i];
		HT[i].ch=c[i];
		HT[i].parent=0;
		HT[i].lc=0;
		HT[i].rc=0; 
	 } 
	 for(int i=n+1;i<=m;i++)
	 {
	 	HT[i].weight=0;
		HT[i].parent=0;
		HT[i].lc=0;
		HT[i].rc=0; 
	 }

	 for(int i=n+1;i<=m;i++)//创建非叶子节点,建哈夫曼树 
	 {//在HT[1]~HT[i-1]的范围里选择两个parent为0,且weight最小的两个结点,其序号分别赋给s1,s2 
	 	select(HT,i-1,s1,s2);
		 HT[s1].parent=i;
		 HT[s2].parent=i;
		 HT[i].lc=s1;
		 HT[i].rc=s2;
		 HT[i].weight=HT[s1].weight+HT[s2].weight;//生成的新树的权值 
		 	 
	 }
	 cout<<endl;
 } 
 //关于weight的计算即字母出现的次序,选择的时候还要考虑字母表中的顺序
 
 
 //根据哈夫曼树求哈夫曼编码
 void CreateHuffmanCode(HuffmanTree HT,HuffmanCode &HC,int n)
 {//从叶子到根逆向求每个字符的哈夫曼编码,存储在编码表HC中 
      HC=new char*[n+1];//分配存储n个字符编码的编码表空间
	  char* cd=new char[n];//字符串长度最长为n-1,cd[]最后一个位置存放结束符'\0',利用的只有n-1个位置 
	  cd[n-1]='\0'; 
	  for(int i=1;i<=n;i++)//逐个字符求哈夫曼编码 
	  {
	  	int start=n-1;
		int c=i;
		int f=HT[i].parent;
		  while(f!=0)//只要不是根节点,就接着往上 
		  {
		  	start--;
		  	if(HT[f].lc==c)
		  	{
		  		cd[start]='0';
			}
			else
			{
				cd[start]='1';
			}
			 c=f;
			 f=HT[f].parent;//继续向上回溯 
		   } //求出第i个字符的编码 
		   HC[i]=new char[n-start];//为第i个字符编码分配空间 
		   strcpy(HC[i],&cd[start]); 
	   }
      delete cd;
  } 
 
  int main()
  {

    int n;
	cin>>n;
	while(n--) {
	   HuffmanTree HT;
  	   HuffmanCode HC;
  	    char c[M],t[M],h[M];//c[M]用来存输入数据并且输出时按照c[M]顺序t[M]来存去重后
		int w[M]= {};
		//按照ASCII码顺序的字符串,w[M]存t[M]对应的权值
		string s;
		cin>>s;
		int len=s.length();
		for(int i=0,j=1; i<len; i++,j++) {
			c[j]=s[i];
			t[j]=s[i];

		}//数组下标从1开始
		sort(t+1,t+len+1,Rule());
		//aaaadddeeeggjk
		h[0]='0';
		h[1]=t[1];
		w[1]=1;
		int num=1;
		for(int i=2; i<=len; i++) {
			//cout<<"inbigfor"<<endl;
			num++;
			for(int j=i; j<=len; j++) {
				//cout<<"insmallfor"<<endl;
				if(t[j]==t[j-1]) {
					w[num-1]++;
					i++;
					continue;
				} else {
					h[num]=t[i];
					w[num]++;
					break;
				}
			}
		}	 
       int n=strlen(h)-1;
	   CreateHuff(HT,w,h,n);
	   CreateHuffmanCode(HT,HC,n);

	   for(int i=1;i<=len;i++)
	   {
	   	for(int j=1;j<=n;j++)
	   	  if(c[i]==HT[j].ch)
			 {
			 	cout<<HC[j];
			 } 
	   }
	   
	}
    return 0; 
  }
/*2
avvvdddeeeffffgggggjk
eeeffrnvjshvhssnn
*/
  
	 
  
  

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
	 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值