哈夫曼算法构造代码

 更新时间:2013年12月23日 16:12:18   作者:  
这篇文章主要介绍了哈夫曼算法构造代码,有需要的朋友可以参考一下

1.定义

  哈夫曼编码主要用于数据压缩。

  哈夫曼编码是一种可变长编码。该编码将出现频率高的字符,使用短编码;将出现频率低的字符,使用长编码。

  变长编码的主要问题是,必须实现非前缀编码,即在一个字符集中,任何一个字符的编码都不是另一个字符编码的前缀。如:0、10就是非前缀编码,而0、01不是非前缀编码。

2.哈夫曼树的构造

  按照字符出现的频率,总是选择当前具有较小频率的两个节点,组合为一个新的节点,循环此过程知道只剩下一个节点为止。

  对于5个字符A、B、C、D、E,频率分别用1、5、7、9、6表示,则构造树的过程如下:

上面过程对应的哈夫曼树为:

假设规定左边为0,右边为1,则变长编码为:

  A 1:010

  B 5:011

  C 7:10

  D 9:11

  E 6: 00

3.哈夫曼构造代码

复制代码 代码如下:

#include <iostream>
#include <string.h>
using namespace std;
struct Node{
    char c;
    int value;
    int par;
    char tag;    //tag='0',表示左边;tag='1',表示右边
    bool isUsed;    //判断这个点是否已经用过
    Node(){
        par=-1;
        isUsed=false;
    }
};

int input(Node*,int);   //输入节点信息
int buildedTree(Node*,int); //建哈夫曼树
int getMin(Node*,int);  //寻找未使用的,具有最小频率值的节点
int outCoding(Node*,int);   //输出哈夫曼编码

int main ()
{
    int n;
    cin>>n;
    Node *nodes=new Node[2*n-1];
    input(nodes,n);
    buildedTree(nodes,n);
    outCoding(nodes,n);
    delete(nodes);
    return 0;
}

int input(Node* nodes,int n){
    for(int i=0;i<n;i++){
        cin>>(nodes+i)->c;
        cin>>(nodes+i)->value;
    }
    return 0;
}

int buildedTree(Node* nodes,int n){
    int last=2*n-1;
    int t1,t2;
    for(int i=n;i<last;i++){
        t1=getMin(nodes,i);
        t2=getMin(nodes,i);
        (nodes+t1)->par=i; (nodes+t1)->tag='0';
        (nodes+t2)->par=i; (nodes+t2)->tag='1';
        (nodes+i)->value=(nodes+t1)->value+(nodes+t2)->value;
    }
    return 0;
}

int getMin(Node* nodes,int n){
    int minValue=10000000;
    int pos=0;
    for(int i=0;i<n;i++)
    {
        if((nodes+i)->isUsed == false && (nodes+i)->value<minValue){
            minValue=(nodes+i)->value;
            pos=i;
        }
    }
    (nodes+pos)->isUsed=true;
    return pos;
}

int outCoding(Node* nodes,int n){
    char a[100];
    int pos,k,j;
    char tmp;
    for(int i=0;i<n;i++){
        k=0;
        pos=i;
        memset(a,'\0',sizeof(a));
        while((nodes+pos)->par!=-1){
            a[k++]=(nodes+pos)->tag;
            pos=(nodes+pos)->par;
        }
        strrev(a);    //翻转字符串
        cout<<(nodes+i)->c<<" "<<(nodes+i)->value<<":"<<a<<endl;
    }
    return 0;
}

执行示例:

相关文章

  • C++深入探究类与对象之友元与运算符重载

    C++深入探究类与对象之友元与运算符重载

    友元就是让一个函数或者类,访问另一个类中的私有成员;打个比方,这相当于是说:朋友是值得信任的,所以可以对他们公开一些自己的隐私,运算符重载的实质就是函数重载或函数多态,运算符重载是一种形式的C++多态,目的在于让人能够用同名的函数来完成不同的基本操作
    2022-04-04
  • VC中BASE64编码和解码使用详解

    VC中BASE64编码和解码使用详解

    Base64是一种很常用的编码方式,利用它可以将任何二进制的字符编码到可打印的64个字符之中, 这样,不管是图片,中文文本等都可以编码成只有ASCII的纯文本。
    2015-11-11
  • 关于VS2019 C++项目同时出现LNK2005 和LNK1169 error 的解决办法

    关于VS2019 C++项目同时出现LNK2005 和LNK1169 error 的解决办法

    这篇文章主要介绍了关于VS2019 C++项目同时出现LNK2005 和LNK1169 error 的解决办法,本文给大家介绍的非常详细,对大家的学习工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • 使用C语言顺序表数据结构实现栈的代码示例

    使用C语言顺序表数据结构实现栈的代码示例

    这篇文章主要给大家介绍了如何使用C语言顺序表数据结构实现栈,文章通过代码示例介绍的非常详细,对大家的学习或工作有一定的参考价值,需要的朋友可以参考下
    2023-09-09
  • C++构造函数一些常见的坑

    C++构造函数一些常见的坑

    这篇文章主要给大家分享的是C++构造函数一些常见的坑,文章围绕C++构造函数的相关资料展开关于C++构造函数坑的内容,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-01-01
  • 通过c语言调用系统curl动态库的示例详解

    通过c语言调用系统curl动态库的示例详解

    这篇文章中我们将通过一个简单的示例来讲解如何在Ubuntu系统中通过C语言调用动态库(共享库)的方法,我们将使用libcurl库,这是一个基于客户端的URL传输库,广泛用于各种程序和应用中以访问网页和服务器数据,需要的朋友可以参考下
    2024-03-03
  • 使用c++实现OpenCV绘制圆端矩形

    使用c++实现OpenCV绘制圆端矩形

    这篇文章主要介绍了使用c++实现OpenCV绘制圆端矩形,其中着重的讲解了OpenCV使用过程中需要注意的一些小细节,避免浪费大家在开发过程中浪费多余的时间
    2021-08-08
  • C语言编程中函数的基本学习教程

    C语言编程中函数的基本学习教程

    这篇文章主要介绍了C语言编程中函数的基本学习教程,其中着重讲到了传值调用与参数,需要的朋友可以参考下
    2015-12-12
  • 详解C++ 编写String 的构造函数、拷贝构造函数、析构函数和赋值函数

    详解C++ 编写String 的构造函数、拷贝构造函数、析构函数和赋值函数

    这篇文章主要介绍了详解C++ 编写String 的构造函数、拷贝构造函数、析构函数和赋值函数的相关资料,这里提供实例帮助大家理解掌握这部分内容,需要的朋友可以参考下
    2017-08-08
  • C语言详细图解浮点型数据的存储实现

    C语言详细图解浮点型数据的存储实现

    使用编程语言进行编程时,需要用到各种变量来存储各种信息。变量保留的是它所存储的值的内存位置。这意味着,当您创建一个变量时,就会在内存中保留一些空间。您可能需要存储各种数据类型的信息,操作系统会根据变量的数据类型,来分配内存和决定在保留内存中存储什么
    2022-05-05

最新评论