码迷,mamicode.com
首页 > 其他好文 > 详细

霍夫曼编码实现

时间:2015-04-15 20:53:09      阅读:160      评论:0      收藏:0      [点我收藏+]

标签:

先把代码贴了,有时间再写思路。。

二叉树定义:

binaryTree.h

技术分享
  1 #ifndef BINARYTREE_H
  2 #define BINARYTREE_H
  3 #include <iostream>
  4 #include "LinkedQueue.h"
  5 
  6 template<class T>
  7 class BinaryTree;
  8 
  9 
 10 int count;
 11 
 12 template<class T>
 13 class BinaryTreeNode
 14 {
 15     friend class BinaryTree < T > ;
 16     friend void Visit(BinaryTreeNode<T> *);
 17     friend void InOrder(BinaryTreeNode<T> *);
 18     friend void PreOrder(BinaryTreeNode<T> *);
 19     friend void PostOrder(BinaryTreeNode<T> *);
 20     friend void LevelOrder(BinaryTreeNode<T> *);
 21 public:
 22     //构造函数
 23     BinaryTreeNode(){ LeftChild = RightChild = 0; }
 24     BinaryTreeNode(const T& e){ data = e; LeftChild = RightChild = 0; }
 25     BinaryTreeNode(const T& e, BinaryTreeNode *l, BinaryTreeNode *r)
 26     {
 27         data = e;
 28         LeftChild = l;
 29         RightChild = r;
 30     }
 31 
 32     BinaryTreeNode<T>* GetLeft()const{ return LeftChild; }
 33     BinaryTreeNode<T>* GetRight()const{ return RightChild; }
 34     T GetData()const{ return data; }
 35 private:
 36     T data;
 37     BinaryTreeNode<T> *LeftChild;//左子树
 38     BinaryTreeNode<T> *RightChild;//右子树
 39 };
 40 
 41 template<class T>
 42 void Visit(BinaryTreeNode<T> *t)
 43 {
 44     std::cout << t->data << " ";
 45 }
 46 
 47 template<class T>
 48 void PreOrder(BinaryTreeNode<T> *t)
 49 {
 50     if (t)
 51     {
 52         Visit(t);
 53         PreOrder(t->LeftChild);
 54         PreOrder(t->RightChild);
 55     }
 56 }
 57 
 58 template<class T>
 59 void InOrder(BinaryTreeNode<T> *t)
 60 {
 61     if (t)
 62     {
 63         InOrder(t->LeftChild);
 64         Visit(t);
 65         InOrder(t->RightChild);
 66     }
 67 }
 68 
 69 template<class T>
 70 void PostOrder(BinaryTreeNode<T> *t)
 71 {
 72     if (t)
 73     {
 74         PostOrder(t->LeftChild);
 75         PostOrder(t->RightChild);
 76         Visit(t);
 77     }
 78 }
 79 
 80 template<class T>
 81 void LevelOrder(BinaryTreeNode<T> *t)
 82 {
 83     LinkedQueue<BinaryTreeNode<T>*> Q;
 84     while (t)
 85     {
 86         Visit(t);
 87 
 88         if (t->LeftChild)
 89         {
 90             Q.Add(t->LeftChild);
 91         }
 92         if (t->RightChild)
 93         {
 94             Q.Add(t->RightChild);
 95         }
 96 
 97         if (Q.IsEmpty())
 98         {
 99             return;
100         }
101         Q.Delete(t);
102 
103     }
104 }
105 
106 
107 template<class T>
108 class BinaryTree
109 {
110 public:
111     BinaryTree(){
112         root = NULL;
113     }
114 
115     //复制构造函数
116     BinaryTree(const BinaryTree<T> &t);
117     ~BinaryTree(){ };//Delete(); };
118     bool IsEmpty() const{ return root == NULL };
119     bool Root(T& x)const;
120     void MakeTree(const T& element, BinaryTree<T>& left, BinaryTree<T>& right);
121     void BreakTree(T& element, BinaryTree<T> &left, BinaryTree<T> &right);
122     void FreeTree(){ Delete(); };
123     void PreOrder(void(*Visit)(BinaryTreeNode<T> *u))const
124     {
125         PreOrder(Visit, root);
126     }
127     void InOrder(void(*Visit)(BinaryTreeNode<T> *u))const
128     {
129         InOrder(Visit, root);
130     }
131     void PostOrder(void(*Visit)(BinaryTreeNode<T> *u))const
132     {
133         PostOrder(Visit, root);
134     }
135 
136     BinaryTreeNode<T>* CopyTree(const BinaryTreeNode<T>* t);//复制树
137 
138     void PrintTree()const;
139     void LevelOrder(void(*Visit)(BinaryTreeNode<T> *u))const;
140     void PreOutput()const;
141     void InOutput()const;
142     void PostOutput()const;
143     void LevelOutput()const;
144     void Delete();
145     int Height()const
146     {
147         return Height(root);
148     }
149 
150     int Size();
151 
152     BinaryTreeNode<T>* GetRoot()const{ return root; }
153 private:
154     BinaryTreeNode<T> *root;
155     void PreOrder(void(*Visit)(BinaryTreeNode<T> *u), BinaryTreeNode<T> *t)const;
156     void InOrder(void(*Visit)(BinaryTreeNode<T> *u), BinaryTreeNode<T> *t)const;
157     void PostOrder(void(*Visit)(BinaryTreeNode<T> *u), BinaryTreeNode<T> *t)const;
158     int Height(BinaryTreeNode<T> *t)const;
159 
160 
161     static void output(BinaryTreeNode<T> *t)
162     {
163         std::cout << t->data <<  ;
164     }
165 
166     static void freeNode(BinaryTreeNode<T> *t)
167     {
168         delete t;
169         t = NULL;
170     }
171 
172     static void ctsize(BinaryTreeNode<T> *t)
173     {
174         ++count;
175     }
176 
177 };
178 
179 template<class T>
180 void BinaryTree<T>::PrintTree()const
181 {
182 
183 }
184 
185 template<class T>
186 BinaryTreeNode<T>* BinaryTree<T>::CopyTree(const BinaryTreeNode<T>* t)
187 {
188     BinaryTreeNode<T>* Node = NULL;
189     if (t)
190     {
191         BinaryTreeNode<T>* lchild = CopyTree(t->LeftChild);
192         BinaryTreeNode<T>* rchild = CopyTree(t->RightChild);
193         Node = new BinaryTreeNode<T>(t->data, lchild, rchild);
194     }
195 
196     return Node;
197 }
198 
199 template<class T>
200 BinaryTree<T>::BinaryTree(const BinaryTree<T> &t)
201 {
202     root = CopyTree(t.root);
203 }
204 
205 
206 
207 template<class T>
208 int BinaryTree<T>::Size()
209 {
210     count = 0;
211     PreOrder(ctsize);
212     return count;
213 }
214 
215 template<class T>
216 int BinaryTree<T>::Height(BinaryTreeNode<T> *t)const
217 {
218     if (!t)
219     {
220         return 0;
221     }
222 
223     int ll = Height(t->LeftChild);
224     int lr = Height(t->RightChild);
225 
226     if (ll > lr)
227     {
228         return ++ll;
229     }
230     else
231         return ++lr;
232 }
233 
234 template<class T>
235 bool BinaryTree<T>::Root(T& x) const
236 {
237     if (root)
238     {
239         x = root->data;
240         return true;
241     }
242     return false;
243 }
244 
245 template<class T>
246 void BinaryTree<T>::MakeTree(const T& element, BinaryTree<T>& left, BinaryTree<T>& right)
247 {
248     if (&left == &right)
249     {
250         BinaryTree<T> newTree(right);
251         if (&left != this)
252         {
253             root = new BinaryTreeNode<T>(element, left.root, newTree.root);
254         }
255         else
256         {
257             BinaryTree<T> newTree2(left);
258             root = new BinaryTreeNode<T>(element, newTree2.root, newTree.root);
259         }
260     }
261     else if (&left == this)
262     {
263         BinaryTree<T> newTree(left);
264         root = new BinaryTreeNode<T>(element, newTree.root, right.root);
265     }
266     else if (this == &right)
267     {
268         BinaryTree<T> newTree(right);
269         root = new BinaryTreeNode<T>(element, left.root, newTree.root);
270     }
271     else
272         root = new BinaryTreeNode<T>(element, left.root, right.root);
273 
274     left.root = right.root = NULL;
275 }
276 
277 template<class T>
278 void BinaryTree<T>::BreakTree(T& element, BinaryTree<T> &left, BinaryTree<T> &right)
279 {
280     if (root == NULL)
281     {
282         std::cerr << "树为空,不能拆分" << std::endl;
283         return;
284     }
285 
286     BinaryTree<T> newTree = *this;
287     element = newTree.root->data;
288     left.root = newTree.root->LeftChild;
289     right.root = newTree.root->RightChild;
290 
291     delete root;
292     root = NULL;
293 }
294 
295 template<class T>
296 void BinaryTree<T>::PreOrder(void(*Visit)(BinaryTreeNode<T> *u), BinaryTreeNode<T> *t)const
297 {
298     if (t)
299     {
300         Visit(t);
301         cout << endl;
302         cout<<"leftChild is: "
303         PreOrder(Visit, t->LeftChild);
304         PreOrder(Visit, t->RightChild);
305     }
306 }
307 
308 template<class T>
309 void BinaryTree<T>::InOrder(void(*Visit)(BinaryTreeNode<T> *u), BinaryTreeNode<T> *t)const
310 {
311     if (t)
312     {
313         InOrder(Visit, t->LeftChild);
314         Visit(t);
315         InOrder(Visit, t->RightChild);
316     }
317 }
318 
319 template<class T>
320 void BinaryTree<T>::PostOrder(void(*Visit)(BinaryTreeNode<T> *u), BinaryTreeNode<T> *t)const
321 {
322     if (t)
323     {
324         PostOrder(Visit, t->LeftChild);
325         PostOrder(Visit, t->RightChild);
326         Visit(t);
327     }
328 }
329 
330 template<class T>
331 void BinaryTree<T>::LevelOrder(void(*Visit)(BinaryTreeNode<T> *u))const
332 {
333     LinkedQueue<BinaryTreeNode<T>* > Q;
334     BinaryTreeNode<T> *t = root;
335     while (t)
336     {
337         cout << "root is ";
338         Visit(t);
339         cout << endl;
340 
341         if (t->LeftChild)
342         {
343             Q.Add(t->LeftChild);
344             cout << "Leftchild of " << t->data << " is:";
345             Visit(t->LeftChild);
346             cout << endl;
347         }
348         else
349         {
350             cout << t->data << " have no leftchild" << endl;
351         }
352         if (t->RightChild)
353         {
354             Q.Add(t->RightChild);
355             cout << "Rightchild of " << t->data << " is:";
356             Visit(t->RightChild);
357             cout << endl;
358         }
359 
360         else
361         {
362             cout << t->data << " have no Rightchild" << endl;
363         }
364 
365         if (Q.IsEmpty())
366         {
367             return;
368         }
369         Q.Delete(t);
370     }
371 }
372 
373 template<class T>
374 void BinaryTree<T>::PreOutput()const
375 {
376     PreOrder(output, root);
377 }
378 
379 template<class T>
380 void BinaryTree<T>::InOutput()const
381 {
382     InOrder(output, root);
383 }
384 
385 template<class T>
386 void BinaryTree<T>::PostOutput()const
387 {
388     PostOrder(output, root);
389 }
390 
391 template<class T>
392 void BinaryTree<T>::LevelOutput()const
393 {
394     LevelOrder(output);
395 }
396 
397 template<class T>
398 void BinaryTree<T>::Delete()
399 {
400     PostOrder(freeNode, root);
401     root = NULL;
402 }
403 #endif
View Code

队列定义:

LinkedQueue.h:

技术分享
  1 #ifndef LINKEDQUEUE_H
  2 #define LINKEDQUEUE_H
  3 #include <iostream>
  4 #include <new>
  5 #include "exceptionerror.h"
  6 
  7 template<class T>
  8 class LinkedQueue;//声明模板类
  9 
 10 template<class T>
 11 class Node
 12 {
 13 public:
 14     friend class LinkedQueue < T > ;//声明为友元,因为需要访问Node的私有成员
 15     friend std::ostream& operator<<(std::ostream& output, const LinkedQueue<T>& q);
 16 private:
 17     Node<T> *next;
 18     T data;
 19 };
 20 
 21 template<class T>
 22 class LinkedQueue
 23 {
 24 public:
 25     LinkedQueue():front(0),rear(0){}
 26     ~LinkedQueue();
 27     friend std::ostream& operator<<(std::ostream& output,const LinkedQueue<T>& q)
 28     {
 29         if (q.IsEmpty())
 30         {
 31             output << "empty queue" << std::endl;
 32         }
 33         else
 34         {
 35             Node<T>* p = q.front;
 36             while (p)
 37             {
 38                 output << p->data << " ";
 39                 p = p->next;
 40             }            
 41         }
 42 
 43         return output;
 44     }
 45     bool IsEmpty()const{ return front == 0; }
 46     bool IsFull()const;
 47     T First()const;//返回第一个元素
 48     T Last()const;//返回最后一个元素
 49     LinkedQueue<T>& Add(const T& x);//添加元素
 50     LinkedQueue<T>& Delete(T& x);//删除元素
 51     int Quantity()const;//返回元素个数
 52 private:
 53     Node<T> *front;
 54     Node<T> *rear;
 55 };
 56 
 57 template<class T>
 58 LinkedQueue<T>::~LinkedQueue()
 59 {
 60     Node<T>* next;
 61     while (front)
 62     {
 63         next = front->next;
 64         delete front;
 65         front = next;
 66     }
 67 }
 68 
 69 template<class T>
 70 bool LinkedQueue<T>::IsFull()const
 71 {
 72     Node<T>* p;
 73     try
 74     {
 75         p = new Node<T>;
 76         delete p;
 77         return false;
 78     }
 79     catch (CMemoryException* e)
 80     {
 81         return true;
 82     }
 83 }
 84 
 85 template<class T>
 86 T LinkedQueue<T>::First()const
 87 {
 88     if (IsEmpty())
 89     {
 90         throw OutofBounds();
 91     }
 92 
 93     return front->data;
 94 }
 95 
 96 template<class T>
 97 T LinkedQueue<T>::Last()const
 98 {
 99     if (IsEmpty())
100     {
101         throw OutofBounds();
102     }
103 
104     return rear->data;
105 }
106 
107 template<class T>
108 LinkedQueue<T>& LinkedQueue<T>::Add(const T& x)
109 {
110     Node<T> *p = new Node<T>;
111     p->data = x;
112     p->next = 0;
113     if (front)
114     {
115         rear->next = p;
116     }
117     else front = p;
118 
119     rear = p;
120     return *this;
121 }
122 
123 template<class T>
124 LinkedQueue<T>& LinkedQueue<T>::Delete(T& x)
125 {
126     if (IsEmpty())
127     {
128         throw OutofBounds();
129     }
130     x = front->data;
131     Node<T>* p = front;//为了释放front空间
132     front = front->next;
133     delete p;
134 
135     return *this;
136 }
137 
138 template<class T>
139 int LinkedQueue<T>::Quantity()const
140 {
141     if (IsEmpty())
142     {
143         return 0;
144     }
145     int count = 0;
146     Node<T>* p = front;
147     while (p)
148     {
149         p=p->next;
150         count++;
151     }
152 
153     return count;
154 }
155 #endif
View Code

exceptionerror.h:

技术分享
 1 #ifndef EXCEPTIONERROR_H
 2 #define EXCEPTIONERROR_H
 3 #include <iostream>
 4 class OutofBounds
 5 {
 6 public:
 7     OutofBounds()
 8     {
 9         std::cerr << "Out of Bounds" << std::endl;
10         //std::exit(1);
11     }
12 };
13 
14 class NoMem
15 {
16 public:
17     NoMem(){
18         std::cerr << "No Memory" << std::endl;
19         //std::exit(1);
20     }
21 
22 };
23 #endif
View Code

最小堆:

MinHeap.h

技术分享
  1 #ifndef MinHeap_H
  2 #define MinHeap_H
  3 
  4 #include<iostream>
  5 #include<algorithm>
  6 #include "exceptionerror.h"
  7 using namespace std;
  8 
  9 template<typename T>
 10 class MinHeap
 11 {
 12 
 13 public:
 14     MinHeap(int MaxHeapSize = 10);
 15     ~MinHeap()
 16     {
 17         if (heap!=NULL)
 18         {
 19             delete[] heap;
 20             heap = NULL;
 21         }
 22     }
 23 
 24     int Size() const{ return CurrentSize; }
 25     T Min()
 26     {
 27         if (CurrentSize==0)
 28         {
 29             throw OutofBounds();
 30         }
 31 
 32         return heap[1];
 33     }
 34 
 35     MinHeap<T>& Insert(const T& x);
 36     MinHeap<T>& DeleteMin(T& x);
 37     void Initialize(T a[], int size, int ArraySize);
 38 private:
 39     int CurrentSize;
 40     int MaxSize;
 41     T* heap;
 42 };
 43 
 44 
 45 
 46 template<typename T>
 47 MinHeap<T>::MinHeap(int MaxHeapSize=10):MaxSize(MaxHeapSize),CurrentSize(0)
 48 {
 49     heap = new T[MaxSize + 1];
 50 }
 51 
 52 template<typename T>
 53 MinHeap<T>& MinHeap<T>::Insert(const T& x)
 54 {
 55     size_t index = ++CurrentSize;
 56     while (index!=1&&x<heap[index/2])
 57     {
 58         heap[index] = heap[index / 2];
 59         index = index / 2;//移向父节点
 60     }
 61 
 62     heap[index] = x;
 63 
 64     return *this;
 65 }
 66 
 67 template<typename T>
 68 MinHeap<T>& MinHeap<T>::DeleteMin(T& x)
 69 {
 70     if (CurrentSize==0)
 71     {
 72         throw OutofBounds();
 73     }
 74 
 75     x = heap[1];
 76     if (CurrentSize==1)
 77     {
 78         --CurrentSize;
 79         return *this;
 80     }
 81     T temp = heap[CurrentSize--];
 82     size_t index = 1;
 83     size_t cindex = 2;
 84     while(cindex<=CurrentSize)
 85     {
 86         if (cindex<CurrentSize&&heap[cindex]>heap[cindex+1])
 87         {
 88             ++cindex;
 89         }
 90 
 91         if (temp<=heap[cindex])
 92         {
 93             break;
 94         }
 95 
 96         heap[index] = heap[cindex];//move down
 97         index = cindex;
 98         cindex *= 2;
 99     }
100 
101     heap[index] = temp;
102     return *this;
103 }
104 
105 template<typename T>
106 void MinHeap<T>::Initialize(T a[], int size, int ArraySize)
107 {
108     delete[] heap;
109     heap = new T[ArraySize + 1];
110     MaxSize = ArraySize;
111     CurrentSize = size;
112 
113     memcpy(heap+1, a, (CurrentSize)*sizeof(T));
114 
115     size_t cindex;
116     for (size_t index = CurrentSize / 2; index >= 1;--index)
117     {
118         T temp = heap[index];
119 
120         cindex = 2 * index;
121         while (cindex<=CurrentSize)
122         {
123             if (cindex<CurrentSize&&heap[cindex + 1]<heap[cindex])
124             {
125                 ++cindex;
126             }
127 
128             if (temp<=heap[cindex])
129             {
130                 break;
131             }
132 
133             heap[cindex/2] = heap[cindex];
134             cindex *= 2;
135         }
136         
137         heap[cindex / 2] = temp;        
138     }
139 
140 }
141 #endif
View Code

Huffman.h:

技术分享
  1 #ifndef HUFFMAN_H
  2 #define HUFFMAN_H
  3 #include<iostream>
  4 #include<fstream>
  5 #include<vector>
  6 #include<string>
  7 #include<stack>
  8 #include<map>
  9 #include<bitset>
 10 #include<iterator>
 11 #include "binaryTree.h"
 12 #include "MinHeap.h"
 13 
 14 using namespace std;
 15 const int NUM_CHARS = 256;
 16 
 17 
 18 struct HuffCode 
 19 {
 20     unsigned int size;
 21     bitset<16> b;
 22 };
 23 
 24 void create_freq_array(size_t freqs[NUM_CHARS], const string& str);
 25 void print_table(const map<char, HuffCode>& m_table);
 26 void create_header(size_t freqs[NUM_CHARS], const map<char, HuffCode>& m_table, string header, unsigned int size);
 27 BinaryTree<char>& HuffmanTree(size_t freqs[NUM_CHARS]);
 28 size_t huffman_compress(vector<unsigned char>& output, const string& input);
 29 map<char, HuffCode>& create_table( map<char, HuffCode>& m_table, size_t freqs[NUM_CHARS], BinaryTree<char>& x);
 30 
 31 size_t compress(map<char, HuffCode>& m_table, unsigned char* compressed, const string& input);
 32 void set_bit(unsigned char* bits, unsigned int pos, unsigned int state);
 33 unsigned int get_bit(unsigned char* bits, unsigned int pos);
 34 unsigned int get_bit(const bitset<16>& b, unsigned int pos);
 35 unsigned int get_bit(unsigned char c, unsigned int pos);
 36 void write_binary(vector<unsigned char>& input, const char* filename);
 37 void read_binary(vector<unsigned char>& output, const char* filename);
 38 size_t huffman_uncompress(const vector<unsigned char>& compressed, vector<unsigned char>& uncompressed);
 39 void uncompress(const BinaryTree<char>& huff_tree, unsigned char* compressed, vector<unsigned char>& uncompress, size_t size);
 40 
 41 
 42 class Huffman
 43 {
 44     friend BinaryTree<char>& HuffmanTree(size_t []);
 45     friend bool operator<(const Huffman& lhs,const Huffman& rhs)
 46     {
 47         return lhs.weight < rhs.weight ? true : false;
 48     }
 49     friend bool operator<=(const Huffman& lhs, const Huffman& rhs)
 50     {
 51         return lhs.weight <= rhs.weight ? true : false;
 52     }
 53 
 54 public:
 55     operator size_t()const { return weight; }
 56     Huffman() :weight(0),tree(){};
 57 private:
 58     BinaryTree<char> tree;
 59     size_t weight;
 60 };
 61 
 62 /************************************************************************/
 63 /*构建霍夫曼树:  
 64 1.建立只包含一个结点的树
 65 2.选取树中权重最小的2棵合并,将合并后的树放入集合中
 66 3.重复2,直到只有一棵树
 67 */
 68 /************************************************************************/
 69 BinaryTree<char>& HuffmanTree(size_t freqs[NUM_CHARS])
 70 {
 71     BinaryTree<char> z, zero;
 72 
 73     int count = 0;
 74     for (int i = 0; i < NUM_CHARS;++i)
 75     {
 76         if (freqs[i])
 77         {
 78             ++count;
 79         }        
 80     }
 81     Huffman *w = new Huffman[count];
 82 
 83     //建立count棵单节点树
 84     int index = 0;
 85     for (int i = 0; i < NUM_CHARS;++i)
 86     {
 87         if (freqs[i])
 88         {
 89             z.MakeTree(static_cast<char>(i), zero, zero);
 90             w[index].weight = freqs[i];
 91             w[index].tree = z;
 92             index++;
 93         }        
 94     }
 95 
 96 
 97     MinHeap<Huffman>H(1);
 98     H.Initialize(w, count, count);//用w初始化最小堆
 99 
100     Huffman x, y;
101 
102     for (int i = 1; i < count;++i)
103     {
104         //选取权重最小的2棵树
105         H.DeleteMin(x);
106         H.DeleteMin(y);
107 
108         //合并这2棵树
109         z.MakeTree(0, x.tree, y.tree);
110         x.weight += y.weight;
111         x.tree = z;
112 
113         //重新插入最小堆
114         H.Insert(x);
115     }
116 
117     H.DeleteMin(x);
118     delete[] w;
119 
120     return x.tree;
121 }
122 
123 //获取字符编码表
124 map<char,HuffCode>& create_table(map<char,HuffCode>& m_table,size_t freqs[NUM_CHARS],BinaryTree<char>& x)
125 {    
126     //vector<string> path(7);
127     vector<BinaryTreeNode<char>* >pPath;//遍历的路径
128     BinaryTreeNode<char>* t = x.GetRoot();
129     stack<BinaryTreeNode<char>*> s;//遍历所用栈
130     string temp;//二进制编码
131     BinaryTreeNode<char>* ttemp=NULL;
132     //前序遍历的循环模式
133     while (t||!s.empty())
134     {
135         //遍历左子树
136         while (t!=NULL)
137         {
138             if (t->GetLeft()==NULL&&t->GetRight()==NULL)
139             {
140                 m_table[t->GetData()].size=temp.size();
141                 m_table[t->GetData()].b = bitset<16>(temp);
142             }
143             s.push(t);
144             pPath.push_back(t);
145 
146             t = t->GetLeft();
147             //左子树存在,编码0
148             if (t!=NULL)
149             {
150                 temp += 0;
151             }
152         }
153         
154         if (!s.empty())
155         {
156             t = s.top();
157             s.pop();
158 
159             ttemp = pPath.back();
160             //路径回溯时将路径中与当前节点不同的节点删除
161             while(ttemp!=t)
162             {
163                 temp.pop_back();
164                 pPath.pop_back();
165                 ttemp = pPath.back();
166             }
167 
168             t = t->GetRight();
169             //右子树存在,编码1
170             if (t!=NULL)
171             {
172                 temp += 1;
173             }
174         }
175 
176     }    
177     
178     //print_table(m_table);
179     return m_table;
180 }
181 
182 
183 void print_table(const map<char,HuffCode>& m_table)
184 {
185     map<char, HuffCode>::const_iterator cit = m_table.cbegin();
186     for (; cit != m_table.cend(); ++cit)
187     {
188         cout << cit->first << " " ;
189         int size = cit->second.size;
190         for (int i = size - 1; i >= 0;--i)
191         {
192             cout << cit->second.b[i];
193         }
194         cout << endl;
195     }
196 }
197 //统计字符频率
198 void create_freq_array(size_t freqs[NUM_CHARS], const string& str)
199 {
200     int i, maxfreq = 0;
201 
202     memset(freqs, 0, sizeof(size_t)*NUM_CHARS);
203     
204     size_t size = str.size();
205     for (i = 0; i < size; ++i)
206     {
207         freqs[(unsigned char)str[i]]++;
208 
209         if (freqs[(unsigned char)str[i]]>maxfreq)
210         {
211             maxfreq = freqs[(unsigned char)str[i]];
212         }
213     }
214 
215     //压缩字节频率
216     if (maxfreq>NUM_CHARS)
217     {
218         for (i = 0; i < NUM_CHARS;++i)
219         {
220             if (freqs[i]>0)
221             {
222                 freqs[i] = static_cast<int>(freqs[i] * (double)NUM_CHARS / maxfreq + 0.5);
223                 if (freqs[i]==0)
224                 {
225                     freqs[i] = 1;
226                 }
227             }
228         }
229     }
230 }
231 
232 
233 void print_freqs(size_t freqs[NUM_CHARS])
234 {
235     for (int i = 0; i < NUM_CHARS;++i)
236     {
237         if (freqs[i])
238         {
239             cout << "char " << static_cast<char>(i) << " freq: "
240                 << freqs[i] << endl;
241         }
242     }
243 }
244 
245 void create_header(size_t freqs[NUM_CHARS], const map<char, HuffCode>& m_table, unsigned char* header, unsigned int size)
246 {
247     memcpy(header, &size, sizeof(int));
248     
249 
250     for (size_t i = 0; i < NUM_CHARS;++i)
251     {
252         header[sizeof(int)+i] = static_cast<unsigned char>(freqs[i]);
253     }
254 
255 }
256 
257 size_t huffman_compress(vector<unsigned char>& compressed, const string& input)
258 {
259     size_t freqs[NUM_CHARS];
260     create_freq_array(freqs, input);
261 
262     print_freqs(freqs);
263     BinaryTree<char> huff_tree;
264 
265     huff_tree = HuffmanTree(freqs);
266     map<char, HuffCode> m_table;
267     create_table(m_table, freqs, huff_tree);
268     print_table(m_table);
269 
270     unsigned int headersize = sizeof(int) + NUM_CHARS;
271     unsigned char* header = new unsigned char[headersize];
272     create_header(freqs, m_table, header, input.size());
273 
274     unsigned char* comstr = new unsigned char[input.size()];
275     memset(comstr, 0, sizeof(char)*input.size());
276     size_t codesize = compress(m_table, comstr, input);
277 
278     cout << "compressed string size(in byte): " << codesize << endl;
279 
280     for (size_t i = 0; i < 8 * codesize;++i)
281     {
282         cout << get_bit(comstr, i);
283     }
284     cout << endl;
285 
286     for (size_t i = 0; i < headersize;++i)
287     {
288         compressed.push_back(header[i]);
289     }
290     for (size_t i = 0; i < codesize;++i)
291     {
292         compressed.push_back(comstr[i]);
293     }
294     
295 
296     delete[] header;
297     delete[] comstr;
298     huff_tree.FreeTree();
299     return headersize+codesize;
300 }
301 
302 // set the bit at position pos in the array bits to the value state
303 void set_bit(unsigned char* bits, unsigned int pos, unsigned int state)
304 {
305     unsigned char mask = 0x80;  // = 128 dec = 10000000 bin
306     for (unsigned int i = 0; i < (pos % 8); i++)
307         mask = mask >> 1;  // shift bitmask to right
308 
309     if (state)
310         bits[pos / 8] = bits[pos / 8] | mask;
311     else
312         bits[pos / 8] = bits[pos / 8] & (~mask);
313 
314     return;
315 }
316 
317 
318 // get the state of the bit at position pos in the array bits
319 unsigned int get_bit(const bitset<16>& b, unsigned int pos)
320 {
321 
322     return b[pos];
323 }
324 
325 unsigned int get_bit(unsigned char* bits,unsigned int pos)
326 {
327     unsigned char mask = 0x80;  // = 128 dec = 10000000 bin
328     /*
329     for (unsigned int i = 0; i < (pos % 8); i++)
330         mask = mask >> 1;  // shift bitmask to right
331         */
332     mask = mask >> (pos % 8);
333 
334     return (((mask & bits[(int)(pos / 8)]) == mask) ? 1 : 0);
335 }
336 
337 unsigned int get_bit(unsigned char c,unsigned int pos)
338 {
339     unsigned char mask = 0x80;
340     mask = mask >> (pos % 8);
341 
342     return (mask&c) == mask ? 1 : 0;
343 }
344 size_t compress(map<char, HuffCode>& m_table, unsigned char* compressed, const string& input)
345 {
346     size_t size = input.size();
347     char c;
348     size_t pos = 0;
349     for (size_t i = 0; i < size;++i)
350      {
351          c = input[i];
352          for (size_t j = 0; j < m_table[c].size;++j)
353          {
354              set_bit(compressed, pos + j, get_bit(m_table[c].b, m_table[c].size-1-j));
355          }
356 
357          pos += m_table[c].size;
358      }
359 
360     /*
361     for (size_t i = 0; i < pos; ++i)
362     {
363         cout << get_bit(compressed, i);
364     }
365     cout << get_bit(compressed, pos + 1);
366     cout << get_bit(compressed, pos + 1);
367     cout << endl;
368     */
369     return (pos / 8 + 1);
370 }
371 
372 void write_binary(vector<unsigned char>& input, const char* filename)
373 {
374     ofstream out(filename, ofstream::binary);
375     out.clear();
376     
377     if (out)
378     {
379         copy(input.begin(), input.end(), ostream_iterator<unsigned char>(out));
380         out.close();
381     }
382     
383 }
384 
385 void read_binary(vector<unsigned char>& output, const char* filename)
386 {
387     unsigned char c;
388     ifstream in("test.bin", ifstream::binary);
389     if (in)
390     {
391         while (!in.eof())
392         {
393             c = in.get();
394             output.push_back(c);
395         }
396         in.close();
397     }
398 }
399 
400 size_t huffman_uncompress(const vector<unsigned char>& compressed, vector<unsigned char>& uncompressed)
401 {
402     unsigned int freqs[NUM_CHARS];
403     unsigned int headersize = sizeof(int) + NUM_CHARS;
404     size_t size = 0;
405     unsigned char* comp = new unsigned char[compressed.size()];
406     for (size_t i = 0; i < compressed.size();++i)
407     {
408         comp[i] = compressed[i];
409     }
410     memcpy(&size, comp, sizeof(int));
411 
412     cout << "size of compressed string(in byte): " << size << endl;
413     
414     for (int i = 0; i < NUM_CHARS;++i)
415     {
416         freqs[i] = (unsigned int)comp[sizeof(int) + i];
417     }
418 
419     BinaryTree<char> huff_tree;
420     huff_tree = HuffmanTree(freqs);
421     uncompress(huff_tree, comp + headersize, uncompressed, size);
422     huff_tree.FreeTree();
423     delete[]comp;
424     
425     return size;
426 }
427 
428 void uncompress(const BinaryTree<char>& huff_tree, unsigned char* compressed, vector<unsigned char>& uncompress, size_t size)
429 {
430     size_t length = 0;
431     unsigned int pos = 0;
432     unsigned int bit;
433 
434     BinaryTreeNode<char>* pNode = NULL;
435     while (length<size)
436     {
437         pNode = huff_tree.GetRoot();
438         while (pNode->GetLeft()!=NULL&&pNode->GetRight()!=NULL)
439         {
440             bit = get_bit(compressed, pos++);
441             if (bit)
442             {
443                 pNode = pNode->GetRight();
444             }
445             else
446                 pNode = pNode->GetLeft();
447         }
448 
449         uncompress.push_back(pNode->GetData());
450         ++length;
451     }
452 }
453 
454 #endif
View Code

附上一篇比较好的介绍文档:

http://pan.baidu.com/s/1gdF3LGB

霍夫曼编码实现

标签:

原文地址:http://www.cnblogs.com/haoliuhust/p/4429661.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!