C++實現:霍夫曼編碼:
- #ifndef CHUFFMANTREE_H_
- #define CHUFFMANTREE_H_
- #include <assert.h>
- #include <iostream>
- #include <string>
- #include <deque>
- using namespace std;
- /***************************************************************************/
- /*先談談霍夫曼編碼的基本思想:
- /*對於一個給定的概率數組,所有元素之和為1,為了便於算法實現,我們擴大100倍
- /*選出序列中最小的兩個元素,刪除原序列中的這兩個數,相加得到一個新的元素
- /*再把新得到的數放入序列中,重復上述過程,直到序列中只有一個元素(100)
- /*規定:1、左孩子必須不大於右孩子節點的值;2、左邊編碼為0,右邊為1
- /***************************************************************************/
- typedef struct _ITEM
- {
- int index;//元素在原來的數組中的索引值
- int data;//數據
- }ITEM,*PITEM;
- typedef struct _TREE
- {
- _TREE* lChild;//指向左孩子
- _TREE* rChild;//指向右孩子
- _TREE* pParent;//指向父節點
- ITEM item;//當前節點的數據域
- }TREE,*PTREE;
- class CHuffmanTree
- {
- public:
- CHuffmanTree(int s[],const int len);
- virtual~ CHuffmanTree();
- //初始化樹
- void InitTree()const;
- //打印輸入的數據
- void ShowBuffer()const;
- //打印樹
- void ShowTree()const;
- void ShowHuffmanCode();
- protected:
- //對隊列元素進行兩次冒泡排序,以便選出最小的兩個數
- void SortDeque();
- //選出隊列中最小的兩個元素構造新的樹節點
- void Select(int& m,int& n);
- //構造哈弗曼樹
- void CreateHuffmanTree();
- private:
- int* pBuffer;//把元素復制到自己的內存裡,指向首地址
- int m_iLength;//數組元素個數
- PTREE pTree;
- deque<ITEM> que;//雙向隊列,在這裡面進行篩選最小的兩個
- };
- #endif;
[cpp] view plaincopyprint?
- #include "stdafx.h"
- #include "HuffmanTree.h"
- CHuffmanTree::CHuffmanTree(int s[], const int len)
- :pBuffer(NULL)
- ,pTree(NULL)
- ,m_iLength(0)
- {
- assert(len>0);
- pBuffer=new int[len];
- int* p=pBuffer;
- for(int i=0;i<len;++i)
- {
- ITEM it;
- it.index=i;
- it.data=s[i];
- que.push_back(it);
- *(p+i)=s[i];
- }
- m_iLength=len;
- pTree=new TREE[2*len-1];
- InitTree();
- }
- CHuffmanTree::~CHuffmanTree()
- {//回收內存
- if(pTree)
- {
- delete[] pTree;
- pTree=NULL;
- }
- if(pBuffer)
- {
- delete[] pBuffer;
- pBuffer=NULL;
- }
- }
- void CHuffmanTree::InitTree() const
- {
- int* p=pBuffer;
- int i=0;
- for(;i<2*m_iLength-1;++i)
- {
- (pTree+i)->lChild=NULL;
- (pTree+i)->rChild=NULL;
- (pTree+i)->pParent=NULL;
- (pTree+i)->item.index=i;
- }
- for(i=0;i<m_iLength;++i)
- (pTree+i)->item.data=*(p+i);
- for(;i<2*m_iLength-1;++i)
- (pTree+i)->item.data=0;
- }
- void CHuffmanTree::ShowBuffer() const
- {
- for(int i=0;i<m_iLength;++i)
- cout<<*(pBuffer+i)<<" ";
- cout<<endl;
- }
- void CHuffmanTree::ShowTree() const
- {
- cout<<"index lChild rChild pParent data"<<endl;
- for(int i=0;i<2*m_iLength-1;++i)
- {
- cout<<(pTree+i)->item.index<<" ";
- if((pTree+i)->lChild)
- cout<<(pTree+i)->lChild->item.data<<" ";
- else
- cout<<"0 ";
- if((pTree+i)->rChild)
- cout<<(pTree+i)->rChild->item.data<<" ";
- else
- cout<<"0 ";
- if((pTree+i)->pParent)
- cout<<(pTree+i)->pParent->item.data<<" ";
- else
- cout<<"0 ";
- cout<<(pTree+i)->item.data<<endl;
- }
-
- }
- void CHuffmanTree::Select(int& m,int& n)
- {
- if(que.size()<2)
- return;
- SortDeque();
- //經過兩次冒泡排序,最小的兩個元素的索引當然是0和1了
- m=que.at(0).index;
- n=que.at(1).index;
- //出隊列
- que.pop_front();
- que.pop_front();
- }
- void CHuffmanTree::SortDeque()
- {
- if(que.empty())
- return;
- //兩次冒泡排序就可以篩選出最小的兩個了
- for(int i=0;i<2;++i)
- {
- for(int j=que.size()-1;j>i;--j)
- {
- if(que.at(j).data<que.at(j-1).data)
- {
- ITEM temp=que.at(j);
- que.at(j)=que.at(j-1);
- que.at(j-1)=temp;
- }
- }
- }
- }
- void CHuffmanTree::CreateHuffmanTree()
- {
- for(int i=m_iLength;i<2*m_iLength-1;++i)
- {
- int m=0,n=0;
- Select(m,n);
- (pTree+m)->pParent=(pTree+i);
- (pTree+n)->pParent=(pTree+i);
- (pTree+i)->lChild=(pTree+m);
- (pTree+i)->rChild=(pTree+n);
- (pTree+i)->item.index=i;
- (pTree+i)->item.data=(pTree+m)->item.data+(pTree+n)->item.data;
- que.push_back((pTree+i)->item);//關鍵!產生的新節點一定要放入隊列中
- }
- }
- void CHuffmanTree::ShowHuffmanCode()
- {
- CreateHuffmanTree();//生成霍夫曼樹
- for(int i=0;i<m_iLength;++i)
- {
- TREE* p=(pTree+i);
- string s="";
- while(p->pParent)
- {//我們約定左0,右1
- if(p->pParent->lChild->item.index==p->item.index)
- s+="0";
- else
- s+="1";
- p=p->pParent;
- }
- s=string(s.rbegin(),s.rend());//逆置
- cout<<(pTree+i)->item.data<<"的編碼為:"<<s<<endl;//打印每個元素的霍夫曼編碼
- }
- }
代碼有注釋,在此不再啰嗦.
測試:
- #include "stdafx.h"
- #include <iostream>
- #include "huffmantree.h"
- using std::cout;
- using std::endl;
-
- int _tmain(int argc, _TCHAR* argv[])
- {
- int s[]={5,29,7,8,14,23,3,11};
- CHuffmanTree tree(s,8);
- tree.ShowBuffer();
- tree.ShowTree();
- tree.ShowHuffmanCode();
- tree.ShowTree();
- return 0;
- }