`

哈夫曼编码与译码

阅读更多
题目的链接为: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; 
}
分享到:
评论

相关推荐

    c++哈夫曼编码与译码

    ### C++实现哈夫曼编码与译码 #### 前言 在计算机科学领域,数据压缩技术是一项非常重要的技能,而哈夫曼编码作为无损数据压缩算法之一,在实际应用中占据着重要地位。本文将详细介绍如何使用C++语言实现哈夫曼...

    数据结构中哈夫曼编码与译码的实现

    在"哈夫曼编码与译码"这个压缩包文件中,可能包含了实现上述过程的代码示例、测试数据以及用于验证编码和译码正确性的工具。通过学习和理解这些文件,我们可以深入理解哈夫曼编码的工作原理,并能够实际操作数据的...

    实验五哈夫曼编码与译码的设计与实现.doc

    哈夫曼编码与译码的设计与实现 本文档介绍了哈夫曼编码与译码的设计与实现,包括哈夫曼树的构造、哈夫曼编码和译码的实现、哈夫曼树的显示等。 一、哈夫曼树的构造 哈夫曼树是一种特殊的二叉树,它的每个结点都有...

    哈夫曼编码与译码器数据结构课程设计报告样本.doc

    哈夫曼编码与译码器数据结构课程设计报告样本 哈夫曼编码是一种变长前缀编码技术,用于数据压缩和编码。该技术由David A. Huffman在1952年提出,广泛应用于数据压缩、图像处理、文本压缩等领域。 在哈夫曼编码中,...

    C++哈夫曼编码与译码课程设计实现源代码

    在C++中实现哈夫曼编码与译码涉及到多个关键概念和技术,下面将详细阐述这些知识点。 1. **哈夫曼树(Huffman Tree)**: 哈夫曼树,也称为最优二叉树,是构建哈夫曼编码的基础。这种树的特点是:频率较高的字符离...

    哈夫曼编码与译码(附报告)

    在本项目中,"哈夫曼编码译码的设计与实现6.0.cpp"文件包含了哈夫曼树的构建和编码解码算法的实现。通过读取"数据.txt"文件获取字符频率,然后构建哈夫曼树,接着将每个字符的编码写入"编码.txt"文件。解码过程则是...

    哈夫曼编码与译码(附源码)借鉴.pdf

    《哈夫曼编码与译码》 哈夫曼编码是一种数据压缩方法,它基于字符出现频率构建最优前缀编码,从而实现高效的数据存储和传输。本文将深入探讨哈夫曼编码的基本原理、构建过程以及其在文件压缩和解压缩中的应用。 1....

    哈夫曼编码与译码的实现.pdf

    《哈夫曼编码与译码的实现》 在信息技术领域,数据压缩技术是不可或缺的一部分,尤其是在互联网通信中,为了高效地传输和存储信息,数据压缩技术的应用显得尤为重要。哈夫曼编码作为一种高效的前缀编码方法,被广泛...

    哈工大数据结构与算法-哈夫曼编码与译码方法.zip

    哈工大的数据结构与算法课程是计算机科学领域中极为重要的基础课程,而哈夫曼编码与译码方法是其中的一项核心内容。哈夫曼编码是一种高效的数据压缩技术,广泛应用于文本压缩、图像压缩以及网络传输等领域。在此,...

    (完整word版)数据结构哈夫曼编码与译码.docx

    总的来说,哈夫曼编码与译码是数据结构和算法的重要应用,它涉及到了二叉树的构建、编码规则的生成和数据的压缩与恢复,对于理解和提高计算机科学中的数据处理能力至关重要。在实际项目中,哈夫曼编码常用于文件压缩...

    哈夫曼编码与译码,支持读取文件进行译码

    哈夫曼编码与译码,支持读取文件进行译码,大家参考啊!!!!!

    哈夫曼树 哈夫曼编码与译码实现(c++)

    信息论课程设计-哈夫曼编码。将英文字符的统计概率作为待编码节点权值。编程得出哈夫曼的码表;输入一段英文字符,利用码表对其编码、译码。显示整个流程

    哈夫曼编码/译码实现

    压缩文件即读文件,统计文件中的字符个数,对文件进行哈夫曼编码和译码,并将编码译码后的字符存储在文件中。 完成功能的详细说明: 1.统计文本文件中各字符的频率(涉及读文件,统计字符个数); 2.对文件中的...

    哈夫曼编码与译码C++源代码

    利用哈夫曼编码来实现对文件的编码、译码、压缩文件、还原文件

    哈夫曼编码与译码 数据结构

    (1)读取文本文件即使用C编译系统所提供的库函数对给定的文本文件(wejian.txt)进行...(5)编写译码函数对前面的编码进行译码处理,打开存储编码的文件(code.txt)根据所读取的编码文件中的每个字符(0、1组成的),

    哈夫曼编码和译码c++

    根据给定文件的信息,我们可以总结出以下关于“哈夫曼编码和译码”的详细知识点: ### 哈夫曼编码简介 哈夫曼编码是一种广泛应用于数据压缩领域的算法,尤其适用于无损数据压缩。该算法是由David A. Huffman在1952...

    哈夫曼编码译码(数据结构课程设计报告+源代码)

    ### 哈夫曼编码译码(数据结构课程设计报告+源代码)解析 #### 数据结构与算法背景 **哈夫曼编码**是一种基于概率的编码技术,广泛应用于数据压缩领域,尤其在图像和视频压缩中表现卓越。其核心原理是在不丢失信息...

Global site tag (gtag.js) - Google Analytics