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;
#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;
}

C++实现:霍夫曼编码_第1张图片


C++实现:霍夫曼编码_第2张图片

 

 

 


 

你可能感兴趣的:(C++,String,struct,tree,null,delete)