哈弗曼编码+行程编码解码

#include <iostream>
#include <cstring>
#include <string>
#include<map>
#include<algorithm>
#include<stdio.h > 
using namespace std;
#define MAXBIT    100
#define MAXVALUE  10000
#define MAXLEAF   256
#define MAXNODE   MAXLEAF*2 -1
typedef struct
{
    double weight;
    int parent;
    int lchild;
    int rchild;
    char value;
} HNodeType;        // 结点结构体 
typedef struct
{
    int bit[MAXBIT];
    int start;
} HCodeType;        //编码结构体 
HNodeType HuffNode[MAXNODE]; // 定义一个结点结构体数组 
HCodeType HuffCode[MAXLEAF];// 定义一个编码结构体数组
// 构造哈夫曼树 
void HuffmanTree (HNodeType HuffNode[MAXNODE],  int n)
{
    /* 
	i、j: 循环变量,m1、m2:构造哈夫曼树不同过程中两个最小权值结点的权值,
    x1、x2:构造哈夫曼树不同过程中两个最小权值结点在数组中的序号。
    */
    int i, j, x1, x2;
    double m1,m2;
    //初始化存放哈夫曼树数组 HuffNode[] 中的结点
    for (i=0; i<2*n-1; i++)
    {
         HuffNode[i].weight = 0;
         HuffNode[i].parent =-1;
         HuffNode[i].lchild =-1;
         HuffNode[i].rchild =-1;
    }
   
    // 构造 Huffman 树 
    for (i=0; i<n-1; i++)
    {//执行n-1次合并
         m1=m2=MAXVALUE;
         //m1、m2中存放两个无父结点且结点权值最小的两个结点 
         x1=x2=-1;
         // 找出所有结点中权值最小、无父结点的两个结点,并合并之为一棵二叉树 
         for (j=0; j<n+i; j++)
         {
              if (HuffNode[j].weight < m1 && HuffNode[j].parent==-1)
              {
                  m2 = m1;
                  x2 = x1;
                  m1 = HuffNode[j].weight;
                  x1 = j;
              }
              else if (HuffNode[j].weight < m2 && HuffNode[j].parent==-1)
              {
                  m2=HuffNode[j].weight;
                  x2=j;
              }
         }
         //设置找到的两个子结点 x1、x2 的父结点信息 
         HuffNode[x1].parent  = n+i;
         HuffNode[x2].parent  = n+i;
         HuffNode[n+i].weight = m1+m2;
         HuffNode[n+i].lchild = x1;
         HuffNode[n+i].rchild = x2;
    }
}
// 哈夫曼树编码 
void HuffmanCode(HCodeType HuffCode[],  int n)
{
    HCodeType cd;       // 定义一个临时变量来存放求解编码时的信息 
    int i,j,c,p;
    for(i = 0;i < n; i++)
    {
        cd.start = n-1;
        c = i;
        p = HuffNode[c].parent;
        while(p != -1)
        {
            if(HuffNode[p].lchild == c)
                cd.bit[cd.start] = 0;
            else
                cd.bit[cd.start] = 1;
            cd.start--;        // 求编码的低一位 
            c = p;
            p = HuffNode[c].parent;    //设置下一循环条件 
        }
        //把叶子结点的编码信息从临时编码cd中复制出来,放入编码结构体数组 
        for (j=cd.start+1; j<n; j++)
           HuffCode[i].bit[j] = cd.bit[j];
        HuffCode[i].start = cd.start;
    }
}
// 哈夫曼解码  
string HuffmanDecode(HNodeType HuffNode[],int n,string s,string destDecode)    // ch是要解码的01串,string是结点对应的字符  
{  int p=2*n-2,c;
    for(int i=0;i<s.length();)
	{
		p=2*n-2;
	   while(HuffNode[p].lchild!=-1&&HuffNode[p].rchild!=-1)	
	   {
	   	    if(s[i++]=='0')
	   	        p=HuffNode[p].lchild;
	   	    else
	   	        p=HuffNode[p].rchild;        
	   }
	   destDecode+=HuffNode[p].value;
	} 
	return destDecode;
}  
bool cmp(HNodeType x,HNodeType y)
{
	return x.weight<y.weight;
}

string runlengthcoding(const string &src)
{
	cout << "=========== Run-Length coding ===========" << endl;
	cout << "Input string   : " << src << endl;

	string destCode;
	/// 在此处添加编码代码,输入为src,输出为destCode
	/// 使用'#'为特殊符号
    int len=src.length();
    char c=src[0],c0;
    int num=1;
    for(int i=1;i<len;i++)
    {
    	if(src[i]==c)
    	   num++;
    	else
		{
		   destCode+=num+'0';
		   if(c>='0'&&c<='9')
		     destCode+='#';
		   if(c=='#')
		     destCode+='#';
		   destCode+=c;
		   c=src[i];
		   num=1;	 	
		}   
		if(i==len-1)//用来记录最后一个字符 
          {
          	  destCode+=num+'0';
          	  if(c>='0'&&c<='9')
		        destCode+='#';
		      if(c=='#')
		        destCode+='#';
                destCode+=c;
		  }	
	}
	cout << "Coded string   : " << destCode << endl;
    
	string destDecode;
	///在此处添加解码代码,输入为destCode,输出为destDecode
    for(int i=0;i<destCode.length();)
    {
    	num=destCode[i++]-'0';
		c=destCode[i++]; 
		c0=destCode[i];
	
		if(c=='#'&&(c0=='#'||c0>='0'&&c0<='9'))
		  {
		  	for(int k=0;k<num;k++)
		      destDecode+=c0;
		      i++;
		  }
		else
		   	for(int k=0;k<num;k++)
		       destDecode+=c;
		    
		   
	}
	cout << "Decoded string : " << destDecode << endl;
	return destDecode;
}

string huffmancoding(const string &src)
{
	cout << "=========== Huffman coding ===========" << endl;
	cout << "Input string   : " << src << endl;

	string destCode;
	
	/// 在此处添加编码代码,输入为src,输出为destCode
	 map<char ,int > word;
    //解析,统计词频
    int l=src.length(),i,n;
    for(int i=0;i<l;i++)
    	++word[src[i]]; 
    i=0;
	n=word.size();
    map<char,int>::iterator it=word.begin();
    while(it != word.end())
    {
        HuffNode[i].value=it->first;
    	HuffNode[i++].weight=(double)(it->second)/(double)l;
        it++;         
    }   
    sort(HuffNode,HuffNode+n,cmp);
	HuffmanTree (HuffNode, n);  // 构造哈夫曼树 
    HuffmanCode(HuffCode, n);  // 哈夫曼树编码 
   
    int j,k;
	for(i=0;i<l;i++)
	{
		for(j=0;j<n;j++)
		    if(HuffNode[j].value==src[i])
		       break;
		for(k=HuffCode[j].start+1;k<n;k++)
		{
			if(HuffCode[j].bit[k])
			   destCode+='1';
			else
			   destCode+='0';
		}
	} 

	cout << "Coded string   : " << destCode << endl;
	cout << "===== Code for each char :" << endl;
	/// 此处输出每个字符的编码
    for(int i=0;i<n;i++)
    {
    	printf("%c ",HuffNode[i].value);
    	for(int j=HuffCode[i].start+1;j<n;j++)
	  	    printf("%d",HuffCode[i].bit[j]);
	  	printf("\n");    
	}
	string destDecode="";
	/// 在此处添加解码代码,输入为destCode,输出为destDecode
    destDecode=HuffmanDecode(HuffNode,n,destCode,destDecode);
	cout << "Decoded string : " << destDecode << endl;
	return destDecode;
}

int main(int argc, char *argv[])
{
	string codename;
	cout<<"请输入你要进行的编码方式(runlength/huffman/all):"<<endl;
	cin>>codename;
	string inputCode;
	cout<<"请输入你要进行编码的字符串(字符串间不能有空格):"<<endl;
	cin>>inputCode;
	if(codename=="runlength") {
		runlengthcoding(inputCode);
	} else if(codename=="huffman") {
		huffmancoding(inputCode);
	} else if(codename=="all") {
		runlengthcoding(inputCode);
		cout<<endl;
		huffmancoding(inputCode);
	} else
		cout << "Cannot recognize your coding name!" << endl;

}

阅读更多
上一篇STL容器中map用法
下一篇51nod 1732
想对作者说点什么? 我来说一句

哈弗曼编码编码解码

2009年03月18日 37KB 下载

没有更多推荐了,返回首页

关闭
关闭