ハフマンツリー構造

ハフマンツリー構造

  1. デザインハフマンツリーノード構造、我々は、デコーダにルートノードから親、lchild、rchild、重量を備えたノード構造をリーフノードとリーフノードへのルートからコーディングを解決する必要があるため。
  2. 我々は、点のハフマン木の概要を知ってN = 2 * N-1、構造体のアレイは、ハフマンツリーのすべてのノードを格納するために使用することができる場合、アレイのサイズはN、添字[0、N-1]でありますリーフノード情報は、(N四角)格納され、[N、N-1]の組合せ情報(N-1乗)を格納するノードの。何として示されていないすべての親ノード、lchild、rchild = -1を、初期化します。割り当て重みは正しい値、または他の割り当てを持っている-1。
  3. 常にアレイ内の最小重量二つのノードを探して、二分木のこれらの二つのルートノードの順序は、生成配列[N、N-1]に加え、その親、lchild、rchild、重みを更新しています。完全な配列、ハフマン木の形まで。
  4. PS:次の番号は、以下にそれらのいずれかよりも左の二つの数字である場合には、選択機能の考え方を達成することが注目され、ユーザーが使用したコードを学ぶ、シンプル、s1とs2の配列の2つの既存のフロントです次いで、小さい方、及びアレイが最小と二番目に小さい番号を残し、完了するまで数を残しました。(また最小とバブルソートの二番目に小さい重みを選択)
#include <iostream>
#include <cstdio>
#include <cstdlib>

using namespace std;

/*哈夫曼树的应用----哈夫曼编码*/

/*
根据哈夫曼算法:
1.若给定n个权值的结点构造n棵二叉树, 其中n棵二叉树的根结点分别为这n个结点,
且其没有左右子树,则这n棵二叉树构成的集合记为为集合F ={T1,T2,T3...Tn} 
2.将集合F中根结点权值之和最小的两棵二叉树作为一个新增结点的左右子树,新增结点的权
值为这两棵二叉树的权值和,将该新增结点构造的二叉树加入集合F中,并从F中删除这两棵树。
3.重复步骤2直到集合F中只含有一棵树为止。(此时该树即为所求哈夫曼树)
*/


//哈夫曼树的结点结构
typedef struct HuffmanTree{
	int weight;
	int parent,lchild,rchild; //编码及译码需要这三个信息 
}HTNode,*HTree; 

typedef char** HuffmanCode;

void HuffmanCoding(HTree& HT,HuffmanCode& HC,int *w,int n);
void select(HTree HT,int t,int&s1,int&s2);

void HuffmanCoding(HTree& HT,HuffmanCode& HC,int *w,int n)
{
	int s1,s2;
	int m;
	int i=0;
	if(n<=1) return;
	m=2*n-1;  //哈夫曼树的结点个数
	HT=(HTNode*)malloc(sizeof(HTNode)*(m)); 
	HTree p=HT;
	for(i=0;i<n;++i,++p,++w)
	{
		//-1表示不存在
		*(p)={*w,-1,-1,-1};  //初始化叶子结点完成 
	}
	for(;i<m;++i,++p)
	{
		*(p)={-1,-1,-1,-1};   //除叶子结点外的结点初始化完成 
	}
	cout<<"初始化后:"<<endl;
	cout<<"双亲"<<'\t'<<"左孩子"<<'\t'<<"右孩子"<<'\t'<<"权值"<<endl;
	for(int i=0;i<7;i++)
	{
		cout<<HT[i].parent<<'\t'<<HT[i].lchild<<'\t'<<HT[i].rchild<<'\t'<<HT[i].weight<<endl;
	}
	for(i=n;i<m;++i)
	{
		//在HT[0..n]中选择parent为0且weight最小的两个结点,其序号分别为s1和s2
		select(HT,i,s1,s2);
		HT[s1].parent=i;
		HT[s2].parent=i;
		HT[i].lchild=s1;
		HT[i].rchild=s2;
		HT[i].weight=HT[s1].weight+HT[s2].weight;
	}
}

void select(HTree HT,int t,int&s1,int&s2)
{
	//在HT[0..n]中选择parent为0且weight最小的两个结点,其序号分别为s1和s2
	int i,m,n;
	m=n=10000;   
	for(i=0;i<t;i++)
	{
		if(HT[i].parent==-1&&(HT[i].weight<m||HT[i].weight<n))
		{
			if(m<n)
			{
				n=HT[i].weight;
				s2=i;
			}
			else
		    {
				m=HT[i].weight;
				s1=i;
			}
		}
	}
	if(s1>s2) //s1放较小的序号
	{
		i=s1;
		s1=s2;
		s2=i;
	}
}

int main()
{
	int w[4]={7,5,2,4};
	HTree HT;
	HuffmanCode HC;
	HuffmanCoding(HT,HC,w,4);
	cout<<'\n'<<"完成后:"<<endl;
	cout<<"双亲"<<'\t'<<"左孩子"<<'\t'<<"右孩子"<<'\t'<<"权值"<<endl;
	for(int i=0;i<7;i++)
	{
		cout<<HT[i].parent<<'\t'<<HT[i].lchild<<'\t'<<HT[i].rchild<<'\t'<<HT[i].weight<<endl;
	}
	return 0;
}

結果:

公開された77元の記事 ウォン称賛19 ビュー10000 +

おすすめ

転載: blog.csdn.net/qq_42932834/article/details/94480949