zoukankan      html  css  js  c++  java
  • 优先队列求解Huffman编码 c++

    1. 优先队列小析

         优先队列的模板: template <class T, class Container = vector<T>,class Compare = less<typename Container::value_type> > class priority_queue;

     可以看出priority_queue的模板声明带有三个参数,T为数据类型,Container为保存数据的容器,,Compare为元素比较方式,其中Container必须是用数组实现的容器,比如vector,deque,不能用list.STL里面容器默认用的是 vector. 比较方式默认用 operator< ,所以如果你把后面俩个参数 缺省的话,优先队列就是大顶堆。如果要用到小顶堆,则一般要把模板的三个参数都带进去。STL里面定义了一个仿函数 greater<Type>,对于基本类型可以用这个仿函数声明小顶堆。引用自(DanielWang_).
      在求解Huffman编码里面,我们需要用到小顶堆性质,而且元素还是指针元素.因此我们使用如下的方式定义优先队列,把模板的三个参数都带进去,并且还自定义了仿函数.

    
    
    typedef struct HTNode{
        char c;
        unsigned int freq;
        HTNode *lchild, *rchild;
    
        //构造函数
        HTNode(char key='', unsigned int fr=0, HTNode *l=NULL, HTNode *r=NULL):
            c(key),freq(fr),lchild(l),rchild(r){};
    
    }HTNode,*pNode;
    
    //重载优先队列里的比较运算符
    struct cmp{
        bool operator()(pNode node1, pNode node2){
            return node1->freq > node2->freq;
        }
    };
    
    //含有指针类型的优先队列
    priority_queue<pNode, vector<pNode>, cmp> pq;
    
    

      2. 具体实现代码 

    
    
    在打印Huffman 编码的时候,还用到了string的一个函数,erase,即删除某个字符.因为end()返回string的最后一个字符的下一个位置,那么就可以用如下的方法删除最后一个字符.
    str.erase(str.end()
    -1); //删除最后一个字符
     
    *************************************************************************
        > File Name: Huffman_code_pg.cpp
        > Author: He Xingjie
        > Mail: gxmshxj@163.com
        > Created Time: 2014年06月06日 星期五 08时57分01秒
        > Description: 
     ************************************************************************/
    #include<iostream>
    #include<queue>
    #include<vector>
    #include<cstdio>
    #include<stack>
    
    using namespace std;
    
    typedef struct HTNode{
        char c;
        unsigned int freq;
        HTNode *lchild, *rchild;
    
        //构造函数
        HTNode(char key='', unsigned int fr=0, HTNode *l=NULL, HTNode *r=NULL):
            c(key),freq(fr),lchild(l),rchild(r){};
    
    }HTNode,*pNode;
    
    //重载优先队列里的比较运算符
    struct cmp{
        bool operator()(pNode node1, pNode node2){
            return node1->freq > node2->freq;
        }
    };
    
    //含有指针类型的优先队列
    priority_queue<pNode, vector<pNode>, cmp> pq;
    
    void HuffmanCode(int n)
    {
        pNode l, r;
    
        //从优先队列中找出优先级最小的两个元素,合并,并
        //把它加入到优先队列中
        while (pq.size() > 1)
        {
            pNode z = new HTNode;
    
            l = pq.top();
            pq.pop();
            r = pq.top();
            pq.pop();
    
            z->lchild = l;
            z->rchild = r;
            z->freq = l->freq + r->freq;
    
            pq.push(z);
        }
    }
    
    void PrintCode(pNode t, string str)
    {
        //中序递归遍历HuffmanTree求解HuffmanCode
        if (t == NULL)
            return;
        if (t->lchild)
        {
            str += '0';
            PrintCode(t->lchild, str);
        }
    
        //叶子节点
        if (t->lchild == NULL && t->rchild == NULL)
        {
            cout<<t->c<<"'s code: "<<str<<endl;
        }
    
        str.erase(str.end()-1);        //删除最后一个字符
    
        if (t->rchild)
        {
            str += '1';
            PrintCode(t->rchild, str);
        }
    }
    
    void DFS(HTNode *t)
    {
        HTNode *node;
        stack<pNode, vector<pNode> > pstack;
    
        pstack.push(t);
        node = pstack.top();
        pstack.pop();
    
        while (pstack.size() > 0)
        {
            if (node->lchild)
            {
                pstack.push(node->lchild);
                node = node->lchild;     
            }
            else if(node->rchild)
            {
                pstack.push(node->rchild);
                node = node->rchild;
            }
            else
            {
                printf("%d ", node->freq);
                node = pstack.top();
                pstack.pop();
            }
        }
    }
    
    int main()
    {
        int n, i;
        FILE *fp;
        char tmp;
        string str;
    
        fp = fopen("in.txt", "r");
        if (fp ==NULL)
        {
            printf("fopen error!
    ");
            return -1;
        }
    
        //输入大小
        fscanf(fp, "%d", &n);
        fscanf(fp, "%c", &tmp);
    
        //输入数据
        for (i=0; i<n; i++)
        {
            char c;
            int freq;
            pNode p = new HTNode;
    
            fscanf(fp, "%c%d", &c, &freq);
            p->c = c;
            p->freq = freq;
            
            fscanf(fp, "%c", &tmp);
    
            pq.push(p);
        }
    
        HuffmanCode(n);
        PrintCode(pq.top(), str);
    
        return 0;
    }
    
    

     参考:

    http://www.cplusplus.com/reference/queue/priority_queue/?kw=priority_queue

    http://blog.csdn.net/liuzhanchen1987/article/details/7856893

    http://blog.csdn.net/daniel_ustc/article/details/17613359

  • 相关阅读:
    动态生成 Excel 文件供浏览器下载的注意事项
    JavaEE 中无用技术之 JNDI
    CSDN 泄露用户密码给我们什么启示
    刚发布新的 web 单点登录系统,欢迎下载试用,欢迎提建议
    jQuery jqgrid 对含特殊字符 json 数据的 Java 处理方法
    一个 SQL 同时验证帐号是否存在、密码是否正确
    PostgreSQL 数据库在 Windows Server 2008 上安装注意事项
    快速点评 Spring Struts Hibernate
    Apache NIO 框架 Mina 使用中出现 too many open files 问题的解决办法
    解决 jQuery 版本升级过程中出现 toLowerCase 错误 更改 doctype
  • 原文地址:https://www.cnblogs.com/Jason-Damon/p/3774370.html
Copyright © 2011-2022 走看看