Huffman Coding 哈夫曼编码

作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4096079.html

使用优先队列实现,需要注意以下几点:

1.在使用priority_queue时,内部需要存储哈夫曼树节点的指针,而不能是节点。因为构建哈夫曼树时,需要把其左右指针指向孩子,而如果储存的是节点,那么孩子的地址是会改变的。同理节点应当使用new在内存中开辟,而不能使用vector,原因是vector在数组大小为2整数次幂时,大小会倍增,开辟新数组并把老数组的数字copy过去,从而也会导致地址变化。

2.优先队列对指针的排列,需要额外写一个比较函数来比较指针指向的节点的大小。bool operator () (wcnode * node1, wcnode * node2) return node1->lessthan(node2);并在定义优先队列时使用这种方法:    priority_queue <wcnode*, vector<wcnode*>, compare> 第一个参数是节点类型,第二个参数是优先队列的储存结构,第三个参数是比较函数。

3.C++在写入文件时,由于只能按字节写入,因此需要把8个bit位转化为一个字节,最后不足8位用0补齐,并记录文件总bit数,便于解码。然后写入文件。另写入二进制文件可以使用ofstream out("output.txt",std::ofstream::binary);

4.哈夫曼编码信息包括每种字符的映射,和该文件的总bit数。

其代码如下:

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <iostream>
  4 #include <cstring>
  5 #include  <fstream>
  6 #include  <queue>
  7 #include  <map>
  8 #include  <vector>
  9 using namespace std;
 10 class compare;
 11
 12 class wcnode
 13 {
 14     public:
 15         friend class compare;
 16         char word;
 17         int count;
 18         wcnode* left;
 19         wcnode* right;
 20         bool lessthan (const wcnode *w)const
 21         {
 22             return count > w->count;
 23         }
 24         wcnode(char w=‘\0‘, int c=0, wcnode* l=NULL, wcnode * r=NULL)
 25         {
 26             word = w; count = c; left = l; right = r;
 27         }
 28 };
 29
 30 class compare
 31 {
 32     public:
 33         bool operator () (wcnode * node1, wcnode * node2)
 34         {
 35             return node1->lessthan(node2);
 36         }
 37 };
 38
 39 void preorder(wcnode *head, vector<bool> rec, map<char, vector<bool> > & res)
 40 {
 41     if( head->left == NULL && head->right == NULL )
 42     {
 43         res[head->word] = rec;
 44         return;
 45     }
 46     vector<bool> l = rec;
 47     l.push_back(0);
 48     vector<bool> r = rec;
 49     r.push_back(1);
 50     if(head->left != NULL) preorder(head->left, l, res);
 51     if(head->right != NULL) preorder(head->right, r, res);
 52 }
 53 map<char, vector<bool> > encode(map<char, int> &wordcount)
 54 {
 55     map<char, vector<bool> > res;
 56     priority_queue <wcnode*, vector<wcnode*>, compare> pq;
 57     map<char, int>::iterator t;
 58     wcnode *tmp;
 59     wcnode *t1, *t2, *t3;
 60
 61     for( t = wordcount.begin() ; t != wordcount.end() ; t++ )
 62     {
 63         tmp = new wcnode();
 64         tmp->word = t->first;
 65         tmp->count = t->second;
 66         pq.push(tmp);
 67     }
 68     while( pq.size() > 1 )
 69     {
 70         t1 = pq.top();
 71         pq.pop();
 72         t2 = pq.top();
 73         pq.pop();
 74         t3 = new wcnode();
 75         t3->count = t1->count + t2->count;
 76         t3->left = t1;
 77         t3->right = t2;
 78         pq.push(t3);
 79     }
 80     wcnode *huffmanhead = pq.top();
 81     vector<bool> rec;
 82     preorder(huffmanhead, rec, res);
 83     map<char, vector<bool>  >::iterator it;
 84     for( it = res.begin() ; it != res.end() ; it++ )
 85     {
 86         cout<<it->first<<":";
 87         for( int i = 0; i < it->second.size() ; i++ )
 88         {
 89             cout<<it->second[i];
 90         }
 91         cout<<", ";
 92     }
 93     return res;
 94 }
 95
 96 void output(string s, string passage, map<char, vector<bool> > res)
 97 {
 98     ofstream out(s.c_str());
 99     vector<bool> bit;
100     for( int i = 0 ; i < passage.size() ; i++ )
101     {
102         vector<bool> tmp = res[passage[i]];
103         for( int i = 0 ; i < tmp.size(); i++ )
104         {
105             bit.push_back(tmp[i]);
106         }
107     }
108     char outputchar = 0;
109     for( int i = 0 ; i < bit.size() ; i++ )
110     {
111         if( i % 8 == 7 )
112         {
113            out.write(&outputchar, sizeof(outputchar));
114            outputchar = 0;
115         }
116         outputchar = outputchar + bit[i];
117         outputchar = outputchar * 2;
118     }
119     if( outputchar != 0 )
120     {
121         out.write(&outputchar, sizeof(outputchar));
122     }
123     out.close();
124 }
125 int main(int argc, char *argv[])
126 {
127     char tmp;
128     ifstream in("Aesop_Fables.txt");
129     map <char, int> wordcount;
130     map <char, vector<bool> > res;
131     string passage;
132     while( in.get(tmp) )
133     {
134         passage += tmp;
135         if( wordcount.count(tmp) == 0  )
136         {
137             wordcount[tmp] = 1;
138         }
139         else
140         {
141             wordcount[tmp]++;
142         }
143     }
144     res = encode(wordcount);
145     output("outAesop.txt", passage, res);
146     in.close();
147 }

 

时间: 2024-10-24 00:24:04

Huffman Coding 哈夫曼编码的相关文章

信源编码算法(费诺编码&amp;&amp;哈夫曼编码)

信源编码算法 费诺编码 Fano coding 哈夫曼编码 Huffman coding 费诺编码 编码步骤 将信源符号按照其概率大小,从大到小排列: 将这一组信源符号分成概率之和尽可能接近或者相等的一组(即两组分别的概率和之间的差尽可能小!): 将上面一组符号编码成0,下面一组编码成1,反之亦可: 将已经分好的组重复步骤2,3,直到不能再进行分组为止: 从左到右一次写出码字. 费诺编码演示 已知: 编码过程为: 哈夫曼编码 Huffman coding 编码步骤 将信源符号按照概率大小从大到小

哈夫曼编码(Huffman coding)的那些事,(编码技术介绍和程序实现)

前言 哈夫曼编码(Huffman coding)是一种可变长的前缀码.哈夫曼编码使用的算法是David A. Huffman还是在MIT的学生时提出的,并且在1952年发表了名为<A Method for the Construction of Minimum-Redundancy Codes>的文章.编码这种编码的过程叫做哈夫曼编码,它是一种普遍的熵编码技术,包括用于无损数据压缩领域.由于哈夫曼编码的运用广泛,本文将简要介绍: 哈夫曼编码的编码(不包含解码)原理 代码(java)实现过程 一

哈夫曼编码的理解(Huffman Coding)

哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,可变字长编码(VLC)的一种.Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫做Huffman编码(有时也称为霍夫曼编码). 哈夫曼编码,主要目的是根据使用频率来最大化节省字符(编码)的存储空间. 简易的理解就是,假如我有A,B,C,D,E五个字符,出现的频率(即权值)分别为5,4,3,2,1,那么我们第一步先取两个最小权值作为左右子树构

数据压缩之经典——哈夫曼编码(Huffman)

(笔记图片截图自课程Image and video processing: From Mars to Hollywood with a stop at the hospital的教学视频,使用时请注意版权要求.) JPEG用哈夫曼编码(Huffman Encoder)作为其符号编码.哈弗曼编码是压缩算法中的经典,它理论上可以将数据编成平均长度最小的无前缀码(Prefix-Free Code). 为什么要进行编码? 关于Lena:莱娜图(Lenna)是指刊于1972年11月号<花花公子>(Pla

数据压缩算法之哈夫曼编码(HUFFMAN)的实现

HUFFMAN编码可以很有效的压缩数据,通常可以压缩20%到90%的空间(算法导论).具体的压缩率取决于数据的特性(词频).如果采取标准的语料库进行编码,一般可以得到比较满意的编码结果(对不同文件产生不同压缩率的折中方法). 本文采取对单独一个文件进行编码的方式来演示此压缩算法的使用. 分为下面几个步骤: 1.统计词频数据 2.词频数据转换成HUFFMAN算法能够处理的类型(本文为HuffmanNode,内部有存储词频和树节点的结构) (1)由输入的HuffmanNode[]数组创建最小优先级队

哈夫曼(Huffman)树与哈夫曼编码

声明:原创作品,转载时请注明文章来自SAP师太技术博客:www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将追究法律责任!原文链接:http://www.cnblogs.com/jiangzhengjun/p/4289610.html 哈夫曼树又称最优二叉树,是一种带权路径长最短的树.树的路径长度是从树根到每一个叶子之间的路径长度之和.节点的带树路径长度为从该节点到树根之间的路径长度与该节点权(比如字符在某串中的使用频率)的乘积. 比如有一串字符串如

哈夫曼(huffman)树和哈夫曼编码

哈夫曼树 哈夫曼树也叫最优二叉树(哈夫曼树) 问题:什么是哈夫曼树? 例:将学生的百分制成绩转换为五分制成绩:≥90 分: A,80-89分: B,70-79分: C,60-69分: D,<60分: E. if (a < 60){ b = 'E'; } else if (a < 70) { b = ‘D’; } else if (a<80) { b = ‘C’; } else if (a<90){ b = ‘B’; } else { b = ‘A’; } 判别树:用于描述分类

(转)哈夫曼(huffman)树和哈夫曼编码

原文地址 哈夫曼树也叫最优二叉树(哈夫曼树) 问题:什么是哈夫曼树? 例:将学生的百分制成绩转换为五分制成绩:≥90 分: A,80-89分: B,70-79分: C,60-69分: D,<60分: E. if (a < 60){ b = 'E'; } else if (a < 70) { b = ‘D’; } else if (a<80) { b = ‘C’; } else if (a<90){ b = ‘B’; } else { b = ‘A’; } 判别树:用于描述分类

哈夫曼(Huffman)树和哈夫曼编码

一.哈夫曼(Huffman)树和哈夫曼编码 1.哈夫曼树(Huffman)又称最优二叉树,是一类带权路径长度最短的树, 常用于信息检测. 定义: 结点间的路径长度:树中一个结点到另一个结点之间分支数目称为这对结点之间的路径长度. 树的路径长度:树的根结点到树中每一结点的路径长度之和. 带权路径长度:从根结点到某结点的路径长度与该结点上权的乘积. 树的带权路径长度:树中所有叶子结点的带权路径长度之和记为WPL. 例如: 对图(a): WPL =9×2+5×2+2×2+3×2=38 对图(b): W