鱼C论坛

 找回密码
 立即注册
查看: 5934|回复: 17

[技术交流] 两种风格的Huffman编码(C++版)

[复制链接]
发表于 2014-2-28 22:19:33 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
最近几天在搞Huffman coding。现在给出两个版本的解决方案都是使用了优先队列。输入数据的运算量是N,Huffman树的运算量是RlogR。第一个版本有decode,但是decode需要根据writeTrie的结果来建立树,进而decode。采用preorder(前序)遍历。

(一)由Java翻译成的C++,但是有所修改(vc6.0亲测可行)
Huffman.cpp
  1. #include <iostream>
  2. #include <string>
  3. #include "GPQ.h"

  4. const int R = 256;

  5. class Huffman
  6. {
  7.         class Node
  8.         {
  9.         public:
  10.                 const char _ch;
  11.                 const int    _freq;
  12.                 Node *_left, *_right;

  13.                 Node(char ch, int freq, Node* left, Node* right)
  14.                         : _ch(ch), _freq(freq), _left(left), _right(right)
  15.                 {}
  16.                 bool isLeaf() { return !_left && !_right; }
  17.                 bool compareTo(Node *that)  { return _freq > that->_freq; }
  18.         };
  19.         struct buf
  20.         {
  21.                 buf(): _id(-1) {}
  22.                 int index() { _id++; return _id; }
  23.                 int _id;
  24.         }id;
  25. public:
  26.         void expand(std::string& trie, std::string& s, int N)
  27.         {
  28.                 id._id = -1;
  29.                 Node *root = readTrie(trie);

  30.                 id._id = -1;
  31.                 for (int i = 0; i < N; ++i)
  32.                 {
  33.                         Node *x = root;
  34.                         while (!(x->isLeaf()))
  35.                         {
  36.                                 if(s[id.index()] == '0')
  37.                                         x = x->_left;
  38.                                 else  x = x->_right;
  39.                         }
  40.                         std::cout << x->_ch;
  41.                 }
  42.         }
  43.         void writeTrie(Node* x)
  44.         {
  45.                 if(x->isLeaf())
  46.                 {
  47.                         std::cout << 1;
  48.                         std::cout << x->_ch;
  49.                         return;
  50.                 }
  51.                 std::cout << 0;
  52.                 writeTrie(x->_left);
  53.                 writeTrie(x->_right);
  54.         }
  55.         Node* readTrie(std::string& trie)
  56.         {
  57.                 if(trie[id.index()] == '1')
  58.                 {
  59.                         char c = trie[id.index()];
  60.                         Node *fresh = new Node(c, 0, 0, 0);
  61.                         return fresh;
  62.                 }
  63.                 Node *x = readTrie(trie);
  64.                 Node *y = readTrie(trie);
  65.                 Node *fresh = new Node('\0', 0, x, y);
  66.                 return fresh;
  67.         }
  68.         void compress(std::string& s)
  69.         {
  70.                 // Tabulate frequency counts.
  71.                 int freq[R] = {0};
  72.                 for (int i = 0; i < s.size(); ++i)
  73.                         freq[s[i]]++;

  74.                 // Build Huffman code trie.
  75.                 Node *root = buildTrie(freq);

  76.                 std::string *st = new std::string [R];
  77.                 buildCode(st, root, "");

  78.                 // Print trie for decoder (recursive).
  79.                 writeTrie(root);
  80.                 std::cout << std::endl;

  81.                 // Use Huffman code to encode input.
  82.                 for (int id = 0; id < s.length(); id++)
  83.                 {
  84.                         std::string code = st[s[id]];
  85.                         std::cout << s[id] << " ";
  86.                         std::cout << code << std::endl;
  87.                 }
  88.         }
  89. private:
  90.         Node* buildTrie(int *freq)
  91.         {
  92.                 GenericPQ<Node*> pq(R);
  93.                 for (int i = 0; i < R; i++)
  94.                         if (freq[i] > 0)
  95.                                 pq.insert(new Node(i, freq[i], 0, 0));
  96.                 while (pq.size() > 1)
  97.                 {
  98.                         Node *x = pq.pop();
  99.                         Node *y = pq.pop();
  100.                         Node *parent = new Node('\0', x->_freq + y->_freq, x, y);
  101.                         pq.insert(parent);
  102.                 }
  103.                 return pq.pop();
  104.         }
  105.         std::string* buildCode(Node* root)
  106.         {
  107.                 std::string *st = new std::string[R];
  108.                 buildCode(st, root, "");
  109.                 return st;
  110.         }
  111.         void buildCode(std::string *st, Node *x, std::string s)
  112.         {
  113.                 if(x->isLeaf()) { st[x->_ch] = s; return; }
  114.                 buildCode(st, x->_left, s + '0');
  115.                 buildCode(st, x->_right, s + '1');
  116.         }
  117. };

  118. int main()
  119. {
  120.         Huffman code;
  121.         std::string sample = "ABRACADABRA!";
  122.         std::string trie = "01A001D01!1C01R1B";
  123.         std::string coder  = "0111110010110100011111001010";
  124.         code.compress(sample);
  125.         code.expand(trie, coder, 12);
  126.     return 0;
  127. }
复制代码
GPQ.h
  1. #if !defined (GPQ_H)
  2. #define GPQ_H

  3. template<class T>
  4. class GenericPQ{
  5. private:
  6.         T    *_pq;               // heap-ordered complete binary tree
  7.         int  _N;                  // in pq[1..N] with pq[0] unused
  8. public:
  9.         GenericPQ(int capacity);
  10.         ~GenericPQ();
  11.         bool isEmpty() { return _N == 0; }
  12.         void insert(T x);
  13.         int   size() { return _N; }
  14.         T    pop();
  15. private:
  16.         void swim(int k);
  17.         void sink(int k);
  18.         //Compare and exchange methods for heap implementations
  19.         bool comp(int i, int j) { return _pq[i]->compareTo(_pq[j]); }
  20.         void swap(int i, int j)
  21.         {
  22.                 T ex   = _pq[i];
  23.                 _pq[i] = _pq[j];
  24.                 _pq[j] = ex;
  25.         }
  26. };

  27. template<class T>
  28. GenericPQ<T>::GenericPQ(int capacity)
  29. :_N(0)
  30. {
  31.         _pq = new T[capacity+1];
  32. }

  33. template<class T>
  34. GenericPQ<T>::~GenericPQ(void)
  35. {
  36.         delete [] _pq;
  37. }

  38. /** Bottom-up reheapify (swim) implementation */
  39. template<class T>
  40. void GenericPQ<T>::swim(int k)
  41. {
  42.         while (k > 1 && comp(k/2, k))
  43.         {
  44.                 swap(k, k/2);
  45.                 k = k/2;
  46.         }
  47. }

  48. template<class T>
  49. void GenericPQ<T>::insert(T x)
  50. {
  51.         _pq[++_N] = x;
  52.         swim(_N);
  53. }

  54. /** Top-down reheapify (sink) implementation **/
  55. template<class T>
  56. void GenericPQ<T>::sink(int k)
  57. {
  58.         while (2*k <= _N)
  59.         {
  60.                 int j = 2*k;
  61.                 if (j < _N && comp(j, j+1)) j++;
  62.                 if (!comp(k, j)) break;
  63.                 swap(k, j);
  64.                 k = j;
  65.         }
  66. }

  67. template<class T>
  68. T GenericPQ<T>::pop()
  69. {
  70.         T min = _pq[1];          // Retrieve max key from top.
  71.         swap(1, _N--);           // Exchange with last item.
  72.         sink(1);                 // Avoid loitering.
  73.         _pq[_N+1] = 0;    // Restore heap property.
  74.         return min;
  75. }

  76. #endif
复制代码
(二)比较本土的C++泛型编程(g++可行,vc6不行,更高版本的vc未测试)
  1. #include <iostream>
  2. #include <queue>
  3. #include <map>
  4. #include <climits> // for CHAR_BIT
  5. #include <iterator>
  6. #include <algorithm>

  7. const int UniqueSymbols = 1 << CHAR_BIT;
  8. const char* SampleString = "this is an example for huffman encoding";

  9. typedef std::vector<bool> HuffCode;
  10. typedef std::map<char, HuffCode> HuffCodeMap;

  11. class INode
  12. {
  13. public:
  14.     const int f;

  15.     virtual ~INode() {}

  16. protected:
  17.     INode(int f) : f(f) {}
  18. };

  19. class InternalNode : public INode
  20. {
  21. public:
  22.     INode *const left;
  23.     INode *const right;

  24.     InternalNode(INode* c0, INode* c1) : INode(c0->f + c1->f), left(c0), right(c1) {}
  25.     ~InternalNode()
  26.     {
  27.         delete left;
  28.         delete right;
  29.     }
  30. };

  31. class LeafNode : public INode
  32. {
  33. public:
  34.     const char c;

  35.     LeafNode(int f, char c) : INode(f), c(c) {}
  36. };

  37. struct NodeCmp
  38. {
  39.     bool operator()(const INode* lhs, const INode* rhs) const { return lhs->f > rhs->f; }
  40. };

  41. INode* BuildTree(const int (&frequencies)[UniqueSymbols])
  42. {
  43.     std::priority_queue<INode*, std::vector<INode*>, NodeCmp> trees;

  44.     for (int i = 0; i < UniqueSymbols; ++i)
  45.     {
  46.         if(frequencies[i] != 0)
  47.             trees.push(new LeafNode(frequencies[i], (char)i));
  48.     }
  49.     while (trees.size() > 1)
  50.     {
  51.         INode* childR = trees.top();
  52.         trees.pop();

  53.         INode* childL = trees.top();
  54.         trees.pop();

  55.         INode* parent = new InternalNode(childR, childL);
  56.         trees.push(parent);
  57.     }
  58.     return trees.top();
  59. }

  60. void GenerateCodes(const INode* node, const HuffCode& prefix, HuffCodeMap& outCodes)
  61. {
  62.     if (const LeafNode* lf = dynamic_cast<const LeafNode*>(node))
  63.     {
  64.         outCodes[lf->c] = prefix;
  65.     }
  66.     else if (const InternalNode* in = dynamic_cast<const InternalNode*>(node))
  67.     {
  68.         HuffCode leftPrefix = prefix;
  69.         leftPrefix.push_back(false);
  70.         GenerateCodes(in->left, leftPrefix, outCodes);

  71.         HuffCode rightPrefix = prefix;
  72.         rightPrefix.push_back(true);
  73.         GenerateCodes(in->right, rightPrefix, outCodes);
  74.     }
  75. }

  76. int main()
  77. {
  78.     // Build frequency table
  79.     int frequencies[UniqueSymbols] = {0};
  80.     const char* ptr = SampleString;
  81.     while (*ptr != '\0')
  82.         ++frequencies[*ptr++];

  83.     INode* root = BuildTree(frequencies);

  84.     HuffCodeMap codes;
  85.     GenerateCodes(root, HuffCode(), codes);
  86.     delete root;

  87.     for (HuffCodeMap::const_iterator it = codes.begin(); it != codes.end(); ++it)
  88.     {
  89.         std::cout << it->first << " ";
  90.         std::copy(it->second.begin(), it->second.end(),
  91.                   std::ostream_iterator<bool>(std::cout));
  92.         std::cout << std::endl;
  93.     }
  94.     return 0;
  95. }
复制代码


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-3-1 08:28:17 | 显示全部楼层
涨姿势了,谢谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-6 23:08:30 | 显示全部楼层
看到一个真正让我佩服的Huffman压缩的代码。大家可以看一下~ 写的很全面
  1. #pragma warning (disable: 4786)  
  2.   
  3. #include <math.h>  
  4. #include <stdlib.h>  
  5.   
  6. #ifdef USE_DOT_H  
  7.     #include <iostream.h>  
  8.     #include <fstream.h>  
  9.     #define USE_STR_DOT_H  
  10. #else  
  11.     #include <fstream>  
  12.     #include <iostream>  
  13.     #if !defined( __BORLANDC__ ) || __BORLANDC__ >= 0x0530  
  14.         using namespace std;  
  15.     #else  
  16.         #define USE_STR_DOT_H  
  17.     #endif  
  18. #endif  
  19.   
  20.   
  21. #ifndef SAFE_STL  
  22.     #include <map>  
  23.     #include <vector>  
  24.     #include <string>  
  25.     #include <queue>  
  26.     #include <functional>  
  27.     #include <algorithm>  
  28.     using namespace std;  
  29. #else  
  30.     #include "map.h"  
  31.     #include "vector.h"  
  32.     #include "string.h"  
  33.     #include "queue.h"  
  34.     #include "functional.h"  
  35.     #include "algorithm.h"  
  36.     #include "StartConv.h"  
  37. #endif  
  38.   
  39.   
  40. #include "Wrapper.h"  
  41.   
  42. class ibstream  
  43. {  
  44.   public:  
  45.     ibstream( istream & is );  
  46.   
  47.     int readBit( );  
  48.     istream & getInputStream( ) const;  
  49.   
  50.   private:  
  51.     istream & in;  
  52.     char buffer;  
  53.     int bufferPos;  
  54. };  
  55.   
  56.   
  57. class obstream  
  58. {  
  59.   public:  
  60.     obstream( ostream & os );  
  61.     ~obstream( );  
  62.   
  63.     void writeBit( int val );  
  64.     void writeBits( const vector<int> & val );  
  65.     ostream & getOutputStream( ) const;  
  66.     void flush( );  
  67.   
  68. private:  
  69.     ostream & out;  
  70.     char buffer;  
  71.     int bufferPos;  
  72. };  
  73.   
  74.   
  75.   
  76. class CharCounter  
  77. {  
  78.   public:  
  79.     CharCounter( );  
  80.     CharCounter( istream & input );  
  81.   
  82.     int getCount( char ch );  
  83.     void setCount( char ch, int count );  
  84.   
  85.   private:  
  86.     map<char,int,less<char> > theCounts;  
  87. };  
  88.   
  89.   
  90. struct HuffNode  
  91. {  
  92.     HuffNode *left;  
  93.     HuffNode *right;  
  94.     HuffNode *parent;  
  95.     int value;  
  96.     int weight;  
  97.   
  98.     HuffNode( int v, int w, HuffNode *lt, HuffNode *rt, HuffNode *pt )  
  99.       : value( v ), weight( w ), left( lt ), right( rt ), parent( pt ) { }  
  100. };  
  101.   
  102.   
  103. class HuffmanTree  
  104. {  
  105.   public:  
  106.     HuffmanTree( );  
  107.     HuffmanTree( const CharCounter & cc );  
  108.   
  109.     enum { ERROR = -3, INCOMPLETE_CODE = -2, END = -1 };  
  110.   
  111.       // Here, vector<int> is usable by ibstream and obstreams  
  112.     vector<int> getCode( int ch );  
  113.     int getChar( const vector<int> & code ) const;  
  114.   
  115.       // Write the encoding table using character counts  
  116.     void writeEncodingTable( ostream & out );  
  117.     void readEncodingTable( istream & in );  
  118.   
  119.   private:  
  120.     CharCounter theCounts;  
  121.     map<int,HuffNode *,less<int> > theNodes;  
  122.     HuffNode *root;  
  123.   
  124.     void createTree( );  
  125.     vector<int> getCode( HuffNode *current );  
  126. };  
  127.   
  128. class Compressor  
  129. {  
  130.   public:  
  131.     static void compress( const string & inFile );  
  132.     static void uncompress( const string & compressedFile );  
  133. };  
  134.   
  135. static const int BITS_PER_CHAR = 8;  
  136. static const int DIFF_CHARS = 256;  
  137. static const int READ_MODE = ios::in | ios::binary;  
  138. static const int WRITE_MODE = ios::out | ios::binary;  
  139.   
  140. int getBit( char pack, int pos )  
  141. {  
  142.     return ( pack & ( 1 << pos ) ) ? 1 : 0;  
  143. }  
  144.   
  145. void setBit( char & pack, int pos, int val )  
  146. {  
  147.     if( val == 1 )  
  148.         pack |= ( val << pos );  
  149. }  
  150.   
  151. ibstream::ibstream( istream & is ) : bufferPos( BITS_PER_CHAR ), in( is )  
  152. {  
  153. }  
  154.   
  155. int ibstream::readBit( )  
  156. {  
  157.     if( bufferPos == BITS_PER_CHAR )  
  158.     {  
  159.         in.get( buffer );  
  160.         if( in.eof( ) )  
  161.             return EOF;  
  162.         bufferPos = 0;  
  163.     }  
  164.   
  165.     return getBit( buffer, bufferPos++ );  
  166. }  
  167.   
  168. istream & ibstream::getInputStream( ) const  
  169. {  
  170.     return in;  
  171. }  
  172.   
  173.   
  174. obstream::obstream( ostream & os ) : bufferPos( 0 ), buffer( 0 ), out( os )  
  175. {  
  176. }  
  177.   
  178. obstream::~obstream( )  
  179. {  
  180.     flush( );  
  181. }  
  182.   
  183. void obstream::flush( )  
  184. {  
  185.     if( bufferPos == 0 )  
  186.         return;  
  187.   
  188.     out.put( buffer );  
  189.     bufferPos = 0;  
  190.     buffer = 0;  
  191. }  
  192.   
  193. void obstream::writeBit( int val )  
  194. {  
  195.     setBit( buffer, bufferPos++, val );  
  196.     if( bufferPos == BITS_PER_CHAR )  
  197.         flush( );  
  198. }  
  199.   
  200. void obstream::writeBits( const vector<int> & val )  
  201. {  
  202.     for( int i = 0; i < val.size( ); i++ )  
  203.         writeBit( val[ i ] );  
  204. }  
  205.   
  206. ostream & obstream::getOutputStream( ) const  
  207. {  
  208.     return out;  
  209. }  
  210.   
  211.   
  212.   
  213. CharCounter::CharCounter( )  
  214. {  
  215. }  
  216.   
  217. CharCounter::CharCounter( istream & input )  
  218. {  
  219.     char ch;  
  220.     while( !input.get( ch ).eof( ) )  
  221.         theCounts[ ch ]++;  
  222. }  
  223.   
  224.   
  225. int CharCounter::getCount( char ch )  
  226. {  
  227.     return theCounts[ ch ];  
  228. }  
  229.   
  230. void CharCounter::setCount( char ch, int count )  
  231. {  
  232.     theCounts[ ch ] = count;  
  233. }  
  234.   
  235.   
  236. HuffmanTree::HuffmanTree( const CharCounter & cc ) : theCounts( cc )  
  237. {  
  238.     root = NULL;  
  239.     createTree( );  
  240. }  
  241.   
  242. HuffmanTree::HuffmanTree( )  
  243. {  
  244.     root = NULL;  
  245. }  
  246.   
  247. vector<int> HuffmanTree::getCode( int ch )  
  248. {  
  249.     if( root == NULL )  
  250.         return vector<int>( );  
  251.     return getCode( theNodes[ ch ] );  
  252. }  
  253.   
  254. vector<int> HuffmanTree::getCode( HuffNode *current )  
  255. {  
  256.     vector<int> v;  
  257.     HuffNode *par = current->parent;   
  258.   
  259.     while( par != NULL )  
  260.     {  
  261.         if( par->left == current )  
  262.             v.push_back( 0 );  
  263.         else  
  264.             v.push_back( 1 );  
  265.         current = current->parent;  
  266.         par = current->parent;   
  267.     }  
  268.     reverse( v.begin( ), v.end( ) );  
  269.     return v;  
  270. }  
  271.   
  272. int HuffmanTree::getChar( const vector<int> & code ) const  
  273. {  
  274.     HuffNode *p = root;  
  275.     for( int i = 0; p != NULL && i < code.size( ); i++ )  
  276.         if( code[ i ] == 0 )  
  277.             p = p->left;  
  278.         else  
  279.             p = p->right;  
  280.   
  281.     if( p == NULL )  
  282.         return ERROR;  
  283.     return p->value;  
  284. }  
  285.   
  286. void HuffmanTree::writeEncodingTable( ostream & out )  
  287. {  
  288.     for( int i = 0; i < DIFF_CHARS; i++ )  
  289.         if( theCounts.getCount( i ) > 0 )  
  290.             out << static_cast<char>( i ) << theCounts.getCount( i ) << endl;  
  291.     out << '\0' << 0 << endl;  
  292. }  
  293.   
  294. void HuffmanTree::readEncodingTable( istream & in )  
  295. {  
  296.     for( int i = 0; i < DIFF_CHARS; i++ )  
  297.         theCounts.setCount( i, 0 );  
  298.   
  299.     char ch;  
  300.     int num;  
  301.     char nl;  
  302.   
  303.     for( ; ; )  
  304.     {  
  305.         in.get( ch );  
  306.         in >> num;  
  307.         in.get( nl );  
  308.         if( num == 0 )  
  309.             break;  
  310.         theCounts.setCount( ch, num );  
  311.     }  
  312.     createTree( );  
  313. }  
  314.   
  315.   
  316. bool operator< ( const HuffNode & lhs, const HuffNode & rhs )  
  317. {  
  318.     return lhs.weight > rhs.weight;  
  319. }  
  320.   
  321. void HuffmanTree::createTree( )  
  322. {  
  323.     priority_queue<Pointer<HuffNode>, vector<Pointer<HuffNode> >,  
  324.                    less<Pointer<HuffNode> > > pq;  
  325.   
  326.     for( int i = 0; i < DIFF_CHARS; i++ )  
  327.         if( theCounts.getCount( i ) > 0 )  
  328.         {  
  329.             HuffNode *newNode = new HuffNode( i, theCounts.getCount( i ), NULL, NULL, NULL );  
  330.             theNodes[ i ] = newNode;  
  331.             pq.push( Pointer<HuffNode>( newNode ) );  
  332.         }  
  333.   
  334.     theNodes[ END ] = new HuffNode( END, 1, NULL, NULL, NULL );  
  335.     pq.push( Pointer<HuffNode>( theNodes[ END ] ) );  
  336.   
  337.     while( pq.size( ) > 1 )  
  338.     {  
  339.         HuffNode *n1 = pq.top( ); pq.pop( );  
  340.         HuffNode *n2 = pq.top( ); pq.pop( );  
  341.         HuffNode *result = new HuffNode( INCOMPLETE_CODE, n1->weight + n2->weight, n1, n2, NULL );  
  342.         n1->parent = n2->parent = result;  
  343.         pq.push( Pointer<HuffNode>( result ) );  
  344.     }  
  345.   
  346.     root = pq.top( );  
  347. }  
  348.   
  349.   
  350. void Compressor::compress( const string & inFile )  
  351. {  
  352.     string compressedFile = inFile + ".huf";  
  353.     ifstream in( inFile.c_str( ), READ_MODE );  
  354.   
  355.     CharCounter countObj( in );  
  356.     HuffmanTree codeTree( countObj );  
  357.   
  358.     ofstream out( compressedFile.c_str( ), WRITE_MODE );  
  359.     codeTree.writeEncodingTable( out );  
  360.     obstream bout( out );  
  361.   
  362.     in.clear( ); in.seekg( 0, ios::beg ); // Rewind the stream  
  363.   
  364.     char ch;  
  365.     while( in.get( ch ) )  
  366.         bout.writeBits( codeTree.getCode( ch & (0xff) ) );  
  367.    
  368.     bout.writeBits( codeTree.getCode( EOF ) );  
  369. }  
  370.   
  371. void Compressor::uncompress( const string & compressedFile )  
  372. {  
  373.     int i;  
  374.     string inFile;  
  375.     string extension;  
  376.   
  377.     for( i = 0; i < compressedFile.length( ) - 4; i++ )  
  378.         inFile += compressedFile[ i ];  
  379.   
  380.     for( ; i < compressedFile.length( ); i++ )  
  381.         extension += compressedFile[ i ];  
  382.   
  383.     if( extension != ".huf" )  
  384.     {  
  385.         cerr << "Not a compressed file" << endl;  
  386.         return;  
  387.     }  
  388.   
  389.     inFile += ".uc";  // for debugging, so as to not clobber original  
  390.     ifstream in( compressedFile.c_str( ), READ_MODE );  
  391.     ofstream out( inFile.c_str( ), WRITE_MODE );  
  392.   
  393.     HuffmanTree codeTree;  
  394.     codeTree.readEncodingTable( in );  
  395.   
  396.     ibstream bin( in );  
  397.     vector<int> bits;  
  398.     int bit;  
  399.     int decode;  
  400.   
  401.     for( ; ; )  
  402.     {  
  403.         bit = bin.readBit( );  
  404.         bits.push_back( bit );  
  405.   
  406.         decode = codeTree.getChar( bits );  
  407.         if( decode == HuffmanTree::INCOMPLETE_CODE )  
  408.             continue;  
  409.         else if( decode == HuffmanTree::ERROR )  
  410.         {  
  411.             cerr << "Error decoding!" << endl;  
  412.             break;  
  413.         }  
  414.         else if( decode == HuffmanTree::END )  
  415.             break;  
  416.         else  
  417.         {  
  418.             out.put( static_cast<char>( decode ) );  
  419.             bits.resize( 0 );  
  420.         }  
  421.     }  
  422. }  
  423.   
  424. int main( int argc, char *argv[] )  
  425. {  
  426.     if( argc < 3 )  
  427.     {  
  428.         cerr << "Usage: " << argv[0] << " -[cu] files" << endl;  
  429.         return 1;  
  430.     }  
  431.   
  432.     string option  = argv[ 1 ];  
  433.   
  434.     for( int i = 2; i < argc; i++ )  
  435.     {  
  436.         string nextFile = argv[ i ];  
  437.         if( option == "-c" )  
  438.             Compressor::compress( nextFile );  
  439.         else if( option == "-u" )  
  440.             Compressor::uncompress( nextFile );  
  441.         else  
  442.         {  
  443.             cerr << "Usage: " << argv[0] << " -[cu] files" << endl;  
  444.             return 1;  
  445.         }  
  446.     }  
  447.   
  448.     return 0;  
  449. }  
  450.   
  451.   
  452. #ifdef SAFE_STL  
  453.     #include "EndConv.h"  
  454. #endif
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-3-9 11:43:29 | 显示全部楼层
我也在用C++写这个。。。。。。
某百科说啥不用STL库。。。。。。目前只实现了优先级队列。。。。。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-3-9 12:47:21 | 显示全部楼层
哇,,,,,代码也太长了吧,,,,,,,,,,,,,
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-10 16:10:36 | 显示全部楼层

加油加油,我写了不短时间。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-3-15 21:59:45 | 显示全部楼层
andalousie 发表于 2014-3-10 16:10
加油加油,我写了不短时间。

我目前写了这么多,看看你能不能找出问题(其实我也不知道问题在哪,没有测试过)
编译这些代码需要编译器支持C++11
main()函数是空的,没写,就不发了
这些代码在我的编译器上能编译成功
  1. #ifndef SORT_H_INCLUDED
  2. #define SORT_H_INCLUDED // 这个头文件提供快速排序算法
  3. /*
  4. **写于2014年2月29日
  5. **星期五
  6. */

  7. template <typename Binary_iterator>
  8. void qsort(Binary_iterator left, Binary_iterator right);

  9. template <typename Binary_iterator>
  10. void qsort(Binary_iterator left, Binary_iterator right)
  11. {
  12.     if (!(left < right))
  13.         return;

  14.     Binary_iterator i = left;
  15.     Binary_iterator j = right;
  16.     auto key = *i; // key的值只有实例化了之后才能确定,因此使用auto自动推断类型

  17.     while (i != j) // 用运算符!=比较的缘故是为了兼容非顺序存储的数据(如队列和链表)
  18.     {
  19.         while (i != j && !(*j < key))
  20.             --j;

  21.         if (i != j)
  22.             *(i++) = *j;

  23.         while (i != j && *i < key)
  24.             ++i;

  25.         if (i != j)
  26.             *(j--) = *i;
  27.     }
  28.     *i = key;
  29.     qsort(left, --i); // 快排前半部分
  30.     ++i; // 这样写是为了可以少定义一个friend operator+(iterator & iter, int i)函数
  31.     qsort(++i, right); // 快排后半部分
  32. }


  33. #endif // SORT_H_INCLUDED
复制代码
  1. #ifndef STATEMENT_H_INCLUDED
  2. #define STATEMENT_H_INCLUDED // 这个头文件提供了关于一些数据结构节点的定义
  3. /*
  4. **写于2014年3月1日
  5. **星期六
  6. */

  7. class HTreeNode // 哈夫曼树的节点
  8. {
  9. private:
  10.     char m_data; // 存储的字符
  11.     unsigned int m_weight; // 节点权值
  12.     HTreeNode * m_lSubTree; // 指向左子树的指针
  13.     HTreeNode * m_rSubTree; // 指向右子树的指针
  14. public:
  15.     typedef HTreeNode * HTree;
  16.     HTreeNode(HTreeNode * l = nullptr, HTreeNode * r = nullptr, const unsigned int w = 0,
  17.              const char d = '\0')
  18.         : m_lSubTree(l), m_rSubTree(r), m_weight(w), m_data(d) {}
  19.     char& data() { return m_data; } // 返回引用的版本可供修改元素的值
  20.     const char data() const { return m_data; }
  21.     unsigned int & weight() { return m_weight; }
  22.     const unsigned int weight() const { return m_weight; }
  23.     HTree& lSubTree() { return m_lSubTree; }
  24.     const HTree lSubTree() const { return m_lSubTree; }
  25.     HTree& rSubTree() { return m_rSubTree; }
  26.     const HTree rSubTree() const { return m_rSubTree; }
  27.     bool operator< (const HTreeNode & t)
  28.     {
  29.         return m_weight < t.m_weight;
  30.     }
  31.     /*
  32.     **不定义operator=() 函数,使用默认的即可,虽然有指针元素,
  33.     **但是没有必要进行深复制
  34.     */
  35. };

  36. template <typename ElemType> // 这个队列可以存储树节点,也可以在解码时存储字符,因此使用模板
  37. class HQueNode // 快速排序算法需要双向迭代器,所以应使用双向队列
  38. {
  39. private:
  40.     ElemType m_data; // 数据域
  41.     HQueNode<ElemType> * m_next; // 指针域,指向后继结点
  42.     HQueNode<ElemType> * m_prev; // 指针域,指向前驱结点
  43.     unsigned int m_weight; // 用于排序
  44.     typedef HQueNode<ElemType> * HQueue; // 这个typedef只能用于简化类内声明,不能为外界可见
  45. public:
  46.     HQueNode(ElemType & d) : m_data(d), m_next(nullptr) {}
  47.     HQueNode() : m_next(nullptr) {}
  48.     ElemType & data() { return m_data; }
  49.     const ElemType data() const { return m_data; }
  50.     HQueue& next() { return m_next; }
  51.     const HQueue next() const { return m_next; }
  52.     HQueue& prev() { return m_prev; }
  53.     const HQueue prev() const { return m_prev; }
  54.     unsigned int& weight() { return m_weight; }
  55.     const unsigned int weight() const { return m_weight; }
  56. };
复制代码
  1. #ifndef QUE_BASE_H_INCLUDED
  2. #define QUE_BASE_H_INCLUDED //这个头文件声明并定义了Bit_que类和Huffman_queue类的基类
  3. /*
  4. **写于2014年3月7日
  5. **星期五
  6. */

  7. #include "statement.h"

  8. template <typename ElemType> class Que_base {
  9. private:
  10.     typedef HQueNode<ElemType>* Link_;
  11.     Link_ front;
  12.     Link_ rear;

  13.     unsigned int length;

  14.     void push_(const ElemType&);

  15. protected:
  16.     ~Que_base(); // 由于这个没有多态析构的必要,将析构函数设为保护的以免外界创建Que_base类对象
  17.     Link_ Rear() { return rear; }
  18.     Link_ Front() { return front; }
  19.     virtual void push(const ElemType& data) { return push_(data); }
  20.     // 这个保护虚函数给了派生类扩展的空间
  21. public:
  22.     Que_base() : front(nullptr), rear(nullptr), length(0) {}
  23.     void enqueue(const ElemType& data) { push(data); } // 将元素加入到队尾
  24.     void dequeue(ElemType&); // 队首元素出队列
  25.     const unsigned int size() const { return length; }
  26.     virtual bool empty() const = 0;
  27. };

  28. template <typename ElemType> void Que_base<ElemType>::push_(const ElemType& data) {
  29.     static unsigned int weight = 0;
  30.     Link_ add = new HQueNode<ElemType>;
  31.     add -> data() = data;
  32.     add -> weight() = weight++;

  33.     ++length;

  34.     if (!front) {
  35.         front = rear = add;
  36.         front -> prev() = nullptr;
  37.     }
  38.     else {
  39.         rear -> next() = add;
  40.         add -> prev() = rear;
  41.         rear = add;
  42.     }
  43. }

  44. template <typename ElemType> Que_base<ElemType>::~Que_base() {
  45.     rear = front;
  46.     while (front) {
  47.         front = front -> next();
  48.         delete rear;
  49.         rear = front;
  50.     }
  51. }

  52. template <typename ElemType> void Que_base<ElemType>::dequeue(ElemType& e) {
  53.     if (length > 0) {
  54.         --length;
  55.         e = front -> data();
  56.         Link_ temp = front;
  57.         front = front -> next();
  58.         delete temp;

  59.         if (front == nullptr)
  60.             rear = front;
  61.     }
  62. }



  63. #endif // QUE_BASE_H_INCLUDED
复制代码
  1. #ifndef HAFFMAN_QUEUE_H_INCLUDED
  2. #define HAFFMAN_QUEUE_H_INCLUDED // 该头文件定义了哈夫曼队列以及迭代器类的实现
  3. /*
  4. **写于2014年3月7日
  5. **星期五
  6. */

  7. #include "sort.h"
  8. #include "statement.h"
  9. #include "que_base.h"

  10. class Huffman_queue : public Que_base<HTreeNode> {
  11. private:
  12.     typedef HQueNode<HTreeNode>* HTree;

  13.     class iterator {
  14.     private:
  15.         HTree pointer;
  16.     public:
  17.         iterator(HTree p = nullptr) : pointer(p) {}
  18.         iterator& operator--();
  19.         iterator operator--(int);
  20.         iterator& operator++();
  21.         iterator operator++(int);
  22.         bool operator!= (const iterator& iter) const { return pointer != iter.pointer;};
  23.         bool operator< (const iterator& iter) const { return pointer -> weight() < (iter.pointer) -> weight(); }
  24.         HTreeNode& operator*() { return pointer -> data(); }
  25.     };

  26.     void push(const HTreeNode&);

  27.     HTree End;

  28. public:
  29.     Huffman_queue() : Que_base(), End(new HQueNode<HTreeNode>) {End -> next() = nullptr; End -> prev() = nullptr;}
  30.     bool empty() const { return size() == 1; }
  31.     iterator begin() { return iterator(Front()); }
  32.     iterator end() { return iterator(End); }
  33. };


  34. #endif // HAFFMAN_QUEUE_H_INCLUDED
复制代码
  1. #include "haffman_queue.h" // 这个源文件实现了哈夫曼队列与迭代器

  2. /*
  3. **写于2014年3月8日
  4. **星期六
  5. */

  6. // 迭代器类实现
  7. Huffman_queue::iterator& Huffman_queue::iterator::operator--() { // 前缀--运算符
  8.         pointer = pointer -> prev();

  9.     return *this;
  10. }

  11. Huffman_queue::iterator& Huffman_queue::iterator::operator++() { // 前缀++运算符
  12.     pointer = pointer -> next();
  13.     return *this;
  14. }

  15. Huffman_queue::iterator Huffman_queue::iterator::operator--(int o) { // 后缀--运算符
  16.     HTree temp = pointer;

  17.     pointer = pointer -> prev();

  18.     return iterator(temp);
  19. }

  20. Huffman_queue::iterator Huffman_queue::iterator::operator++(int o) { // 后缀++运算符
  21.     HTree temp = pointer;

  22.     pointer = pointer -> next();
  23.     return iterator(temp);
  24. }

  25. // 哈夫曼队列实现
  26. void Huffman_queue::push(const HTreeNode& data) {
  27.     Que_base<HTreeNode>::push(data);
  28.     Rear() -> next() = End; // End节点的设置
  29.     End -> prev() = Rear();
  30.     qsort(begin(), end());
  31. }
复制代码
  1. #ifndef BIT_QUE_H_INCLUDED

  2. #define BIT_QUE_H_INCLUDED // 这个头文件定义了一个表示二进制位流的Bit_que类

  3. /*
  4. **写于2014年3月15日
  5. **星期六
  6. */

  7. class Bit_que : public Que_base<bool> {
  8. public:
  9.     bool empty() const { return size() == 0;}
  10. };



  11. #endif // BIT_QUE_H_INCLUDED
复制代码
目前还差哈夫曼树和编码没有实现,代码写了不下500行了吧
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-3-15 22:02:01 | 显示全部楼层
枫界易城 发表于 2014-3-9 12:47
哇,,,,,代码也太长了吧,,,,,,,,,,,,,

哈夫曼编码本来就复杂......你看看我的代码吧
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-3-15 22:06:43 | 显示全部楼层
andalousie 发表于 2014-3-10 16:10
加油加油,我写了不短时间。

发现了吗,我的程序不能用STL就写一个迭代器类模仿STL......求看看有没有问题
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-3-15 22:11:02 | 显示全部楼层
你们好棒啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-3-15 23:51:51 | 显示全部楼层
加油!!!!{:1_1:}{:1_1:}{:1_1:}{:1_1:}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-16 09:29:59 | 显示全部楼层
柠“萌”圆 发表于 2014-3-15 21:59
我目前写了这么多,看看你能不能找出问题(其实我也不知道问题在哪,没有测试过)
编译这些代码需要编译器支 ...

Well, uh... 你的迭代器写的不错啊~ 我反正没看到错误哦~ 反正我是用不惯快排的,所以用了一个堆实现的优先队列解决排序的问题。我其实不太了解C++11的,不过看了你的auto和nullptr的运用似乎懂了点,哈。一般有具体类型的构造函数我就直接用explicit了,这样编译器就不会误会了。你看过我写的《再看Huffman树》吗?上面有我实现的简易的位流。但是不是像你基于queue派生出来的,而是一个类似链表的衍生物。你加油吧,嘻嘻。会写出来的。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-3-16 13:46:30 | 显示全部楼层
andalousie 发表于 2014-3-16 09:29
Well, uh... 你的迭代器写的不错啊~ 我反正没看到错误哦~ 反正我是用不惯快排的,所以用了一个堆实现的优 ...

nullptr其实就是C宏NULL,用于表示空指针,不过比NULL更安全,清晰。auto用于自动类型推断,例如:
std::vector<std::string>::const_itrator p = v.begin();这种冗长的记法可以直接用 auto p = v.begin();减少了输入量,有时会使代码有更好的可读性
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-16 21:43:06 | 显示全部楼层
柠“萌”圆 发表于 2014-3-16 13:46
nullptr其实就是C宏NULL,用于表示空指针,不过比NULL更安全,清晰。auto用于自动类型推断,例如:
std: ...

谢谢呦,基础果然比我扎实~~ 膜拜你。你写的我都能看懂。比书上讲的清楚多了{:1_1:}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-3-19 18:47:54 | 显示全部楼层
andalousie 发表于 2014-3-16 21:43
谢谢呦,基础果然比我扎实~~ 膜拜你。你写的我都能看懂。比书上讲的清楚多了

目前我C++ Programming Language都看得不明白。。。。。。能推荐几本书看看么?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-19 22:41:39 | 显示全部楼层
柠“萌”圆 发表于 2014-3-19 18:47
目前我C++ Programming Language都看得不明白。。。。。。能推荐几本书看看么?

可以看看Data Structures and Problem Solving Using C++,Mark Allen Weiss写的,清华大学出版社出过翻译本。还有C++ Annotations Version 9.7.3,中文叫做C++剖析应该~ Frank B. Brokken写的,可以看看,比Bjarne Stroustrup的神书好懂点。英文版网上都可以下载到。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-3-21 22:16:09 | 显示全部楼层
andalousie 发表于 2014-3-19 22:41
可以看看Data Structures and Problem Solving Using C++,Mark Allen Weiss写的,清华大学出版社出过翻译 ...

哈夫曼编码写出来了,但是崩溃了......貌似在迭代器上出了问题
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-1-2 16:28:33 | 显示全部楼层
路过,了解下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-26 00:13

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表