1. 程式人生 > >資料結構_樹_赫夫曼樹及赫夫曼編碼_C++實現

資料結構_樹_赫夫曼樹及赫夫曼編碼_C++實現

#include<iostream>
#include<stack>
using namespace std;

class NODE
{
public:
	NODE();
	int weight,parent,lchild,rchild;
};

NODE::NODE()
{
	weight=parent=lchild=rchild=0;
}

class HUFFMAN
{
public:
	HUFFMAN();
	void GetHuffmanCode();//獲得赫夫曼編碼主調函式
private:
	void GetHuffmanNode();//獲得節點
	void HuffmanCoding();//編碼
	void PrintHuffmanCode();//輸出編碼
	void Select(int &,int &);//從森林中選擇兩顆權值較小的樹
	int len,cur;//len表示表長度cur表示當前指示的節點
	NODE * HT;//HT指向表頭結點
};

HUFFMAN::HUFFMAN()
{
	len=cur=0;
	HT=NULL;
}

void HUFFMAN::GetHuffmanCode()//獲得赫夫曼編碼主調函式
{
	GetHuffmanNode();
	HuffmanCoding();
	PrintHuffmanCode();
}

void HUFFMAN::GetHuffmanNode()//獲得節點
{
	cout<<"GetHuffmanNode Called !"<<endl<<endl;
	cout<<"Please Enter The Weight Of Each Node ."<<endl<<endl;
	NODE node[100];
	int i=0,t;
	while(cin>>t)
	{
		node[i++].weight=t;
	}
	cin.clear();
	len=i;
	HT=new NODE[2*i];
	for(i=1;i<=len;i++)
		*(HT+i)=node[i-1];
	cur=len+1;
}

void HUFFMAN::HuffmanCoding()//編碼
{
	cout<<"HuffmanCoding Called !"<<endl<<endl;
	while(cur<2*len)//建樹過程
	{
		int a,b;
		Select(a,b);//選擇兩顆權值較小的子樹
		(HT+cur)->weight=(HT+a)->weight+(HT+b)->weight;//連線成新樹並更該其權值
		(HT+cur)->lchild=a;
		(HT+cur)->rchild=b;
		cur++;
	}
}

void HUFFMAN::PrintHuffmanCode()//輸出編碼
{
	cout<<"PrintHuffmanCode Called !"<<endl<<endl;
	cout<<"The Huffman Code Is :"<<endl<<endl;
	stack<int> s;//定義一個棧存放編碼
	for(int i=1;i<=len;i++)//從葉子節點向上查詢到根節點
	{
		cout<<(HT+i)->weight<<" : ";
		int j=i;
		do
		{
			if((HT+(HT+j)->parent)->lchild==j)//左子樹表示為0
				s.push(0);
			else//右子樹表示為1
				s.push(1);
			j=(HT+j)->parent;//j指向其父節點
		}while((HT+j)->parent!=0);//未查詢到根節點時進行查詢
		while(!s.empty())//輸出編碼
		{
			cout<<s.top()<<" ";
			s.pop();
		}
		cout<<endl;
	}
}

void HUFFMAN::Select(int &a,int &b)//從森林中選擇兩顆權值較小的樹
{
	int min;
	bool first=true;
	for(int i=1;i<cur;i++)//從表中獲得min的值並得到a其中有個小技巧不知道您看懂了木有?
	{
		if((HT+i)->parent==0&&(first==true||(HT+i)->weight<min))
		{
			a=i;
			min=(HT+i)->weight;
			if(first==true)
				first=false;
		}
	}
	first=true;
	(HT+a)->parent=cur;//更改a的父節點
	for(int i=1;i<cur;i++)//從表中獲得min的值並得到b
	{
		if((HT+i)->parent==0&&(first==true||(HT+i)->weight<min))
		{
			b=i;
			min=(HT+i)->weight;
			if(first==true)
				first=false;
		}
	}
	(HT+b)->parent=cur;//更改b的父節點
	if(a>b)//如有必要調整a、b次序
	{
		int t=a;
		a=b;
		b=t;
	}
}