哈夫曼编码与译码_C/C++_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > C/C++ > 哈夫曼编码与译码

哈夫曼编码与译码

 2012/5/10 10:39:45  passzh  程序员俱乐部  我要评论(0)
  • 摘要:题目的链接为:http://acm.njupt.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1022题目的描述为:哈夫曼编码与译码时间限制(普通/Java):1000MS/3000MS运行内存限制:65536KByte总提交:343测试通过:123描述已知电文包括的字符集为{A,C,I,M,N,P,T,U},输入对应权值,对字符集合进行哈夫曼编码,完成电文的哈夫曼编码与译码工作。输入共三行:第一行为对应字符集{A
  • 标签:哈夫曼 编码 译码
题目的链接为:http://acm.njupt.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1022
题目的描述为:
哈夫曼编码译码
时间限制(普通/Java):1000MS/3000MS          运行内存限制:65536KByte
总提交:343            测试通过:123

描述

已知电文包括的字符集为{A,C,I,M,N,P,T,U},输入对应权值,对字符集合进行哈夫曼编码,完成电文的哈夫曼编码与译码工作。

输入


共三行:
第一行为对应字符集{A,C,I,M,N,P,T,U}的权值
第二行为一段字符串表示的电文(长度不超过1000);
第三行为一段电文的哈夫曼编码。

输出


共十行:

前八行为各字符的编码;

第九行是与第二行输入对应的哈夫曼编码;

第十行是与第三行输入对应的电文。


样例输入

1 2 3 4 5 6 7 8
NUPTICPCACM
1111011111100

样例输出

A: 11110
C: 11111
I: 1110
M: 100
N: 101
P: 110
T: 00
U: 01
1010111000111011111110111111111011111100
ACM

哈弗曼编码,是一种很常用的压缩数据的方式。它将频率出现得高的用短编码,频率出现得低的字母用长编码。对哈夫曼编码的理解,就是对压缩的理解。
如对于A,C,I,M,N,P,T,U
他们出现的频率为1,2,3,4,5,6,7,8
首先将他们全都变为单个的树节点,然后将权重小的组成树,即选择1,2组成树,这个树的权重为3,左子树为1,右子树为2,将新的树放入集合。
3(1,2),3,4,5,6,7,8
最小的是权重为3的两颗树,将其合并为新的树,并放入集合:
4,5,6,6(3(1,2),3),7,8
依次类推,就可以建立一颗哈弗曼树。哈夫曼树从节点到左子树根节点为0,到右子树根节点为1。按照这个规则,我们可以根据从根节点到叶子节点的路径,得知叶子节点所代表的字母的编码。译码即逆向思维
其实对树比较熟悉的话,这道题比较容易就能够做出来。
代码如下:
#include<iostream>
#include<algorithm>
#include<string>
#define MAXNUM 1001
using namespace std;
//哈夫曼树的节点
typedef struct node{

    //树节点的标志 
    char data;      
    //树节点的权重
    int weight;
    //左右孩子
    int lchild;
    int rchild;
    //是否已经被放入树中 
    bool tag; 
}myNode; 
bool compare(myNode mynode1,myNode mynode2)
{
    return mynode1.weight<mynode2.weight; 
}
myNode nodes[100];
char mycode[100];
char ch[]={'A','C','I','M','N','P','T','U'};
int index=-1;
int index1=-1;
//记录每个字母的哈弗曼编码 
string str[8];
myNode recordNode;
bool judge()
{
   int record=0;
   for(int i=0;i<=index;i++)
   {
        if(nodes[i].tag==false)
        {
           record++;
           recordNode=nodes[i];
        } 
   } 
   if(record==0||(record==1&&recordNode.data=='#'))
   {
        return true;
   }
   return false;
}
int findNode()
{
   for(int i=0;i<=index;i++)
   {
        if(nodes[i].tag==false)
        {
             nodes[i].tag=true;
             return i;
        }
   } 
   return -1;
}
//编码
bool code(myNode *root,char ch1)
{
   bool tag=false;
   if(root->data==ch1)
   {
         return true; 
   }
   int arr[2];
   arr[0]=root->lchild;
   arr[1]=root->rchild;
   for(int i=0;i<2;i++)
   {
       if(arr[i]!=-1)
       {   
           tag=code(&nodes[arr[i]],ch1);
           if(tag)
           {
               if(i==0)
               {
                      mycode[++index1]='0'; 
               } 
               else if(i==1)
               {
                      mycode[++index1]='1'; 
               } 
           } 
           if(tag)
           {
                return tag; 
           }
       } 
   }

   return tag;
} 
//创建哈弗曼树 
void createTree()
{
    while(!judge())
    {
         //按照权重由小到大排序 
         sort(nodes,nodes+index+1,compare); 
            
         myNode newNode;
         newNode.data='#';
         newNode.lchild=findNode();
         newNode.rchild=findNode();
         newNode.weight=nodes[newNode.lchild].weight+nodes[newNode.rchild].weight;
         newNode.tag=false;
       
         nodes[++index]=newNode;
    }
}
//输出字母对应的编码 
void outputCode(char cha)
{
    for(int i=0;i<8;i++)
    {
         if(cha==ch[i])
         {
             cout<<str[i];
             break; 
         } 
    }
}
//译码
void decode1(string inputstr)
{
    int kkindex=-1;
    int len=inputstr.length();
    while(kkindex<len)
    {
           bool find=false;
           myNode tempNode=nodes[index];
           char ch;
           while(!find&&kkindex<len)
           {
                  ++kkindex;
                  if(inputstr[kkindex]=='0')
                  {
                       tempNode=nodes[tempNode.lchild]; 
                  }
                  else
                  {
                       tempNode=nodes[tempNode.rchild];
                  }
                  ch=tempNode.data;
                  if(ch!='#')
                  {
                        find=true;
                  }
           }
           if(ch!='#')
           {
              cout<<ch;
           }
    }
} 
void input()
{
    for(int i=0;i<8;i++)
    {
         int data;
         cin>>data;
         
         nodes[++index].data=ch[i];
         nodes[index].weight=data;
         nodes[index].lchild=-1;
         nodes[index].rchild=-1;
         nodes[index].tag=false;
    } 
    
    //构造哈夫曼树 
    createTree();
    
    //recordNode故为树的根 
    for(int i=0;i<8;i++)
    {
         index1=-1;
         code(&(nodes[index]),ch[i]);
         str[i]="";
         for(int j=index1;j>=0;j--)
         {
             str[i]+=mycode[j];
         }
    }
    
    //输出
    for(int i=0;i<8;i++)
    {
         cout<<ch[i]<<": ";
         cout<<str[i]<<endl; 
    } 
    
    //获得输入的字符串
    string inputstr;
    cin>>inputstr;
    for(int i=0;i<inputstr.length();i++)
    {
        outputCode(inputstr[i]); 
    } 
    cout<<endl;
    
    //输出译码结果
    cin>>inputstr; 
    decode1(inputstr);
    cout<<endl;
}
int main()
{
   input();
   
   system("pause");
   return 0; 
}
发表评论
用户名: 匿名