zoukankan      html  css  js  c++  java
  • 霍夫曼编码实现

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

    二叉树定义:

    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

  • 相关阅读:
    读大道至简有感
    动手动脑7
    大道至简第七章第八章
    课后作业(接口与继承)
    大道至简第六章
    课后题以及动手动脑1 3题
    大道至简第五章
    课后作业和动手动脑(字符串)
    大道至简第四章
    课后作业及动手动脑
  • 原文地址:https://www.cnblogs.com/haoliuhust/p/4429661.html
Copyright © 2011-2022 走看看