ハフマンツリーの基本概念と作成(c / c ++)

1.いくつかの基本的な概念

1.パス:ツリー内のあるノードから別のノードへの分岐は、これら2つのノード間のパスを構成します。
2.パス長パス上の分岐の数はパス長と呼ばれます。
3.ツリーのパス長ツリーのルートから各ノードまでのパス長の合計
4.右:エンティティに割り当てられた数量は、エンティティの一部または一部の属性の数値記述です。
5.ノードの加重パス長:ノードからツリーのルートまでのパスの長さとノードの重みの積。
6.ツリーの加重パス長:ツリー内のすべての葉ノードの加重パス長の合計
ここに画像の説明を挿入
通常は次のように記録されます。7。ハフマンツリー:m個の加重{w1、w2、...、wm}があるとします。 、n個のリーフノードを持つバイナリツリーを構築でき、各リーフノードの重みはwiです。重み付きパス長WPLが最小のバイナリツリーは、最適なバイナリツリーまたはハフマンツリーと呼ばれます。
注:
(1)完全な二分木は必ずしもハフマンツリーである必要はありません;
(2)重みが大きいノードはルートノードに近いです;
(3)ハフマンツリーは一意ではありませんが、ツリーの重み付きパス長です確かに等しい;

次に、ハフマンツリーを構築します

ハフマンツリーノード構造:ハフマンツリーの
ここに画像の説明を挿入
ストレージ表現

typedef struct{
    
    
 int weight;  //结点的权值
 int parent,lchild,rchild;  //结点的双亲、左孩子、右孩子的下标
}HTNode,*HuffmanTree;  //动态分配数组存储哈夫曼树

ハフマンツリーノードの数:
ここに画像の説明を挿入

例:w =(5,29,7,8,14,23,3,11)とすると、ハフマンツリーを生成し、ツリーの加重パス長を計算します。そして、その構築中のストレージ構造HTの初期状態と最終状態を示します。

ここに画像の説明を挿入
ここに画像の説明を挿入

ここに画像の説明を挿入
【アルゴリズムの説明】

void CreateHT(HuffmanTree &HT,int n)
{
    
    
  if(n<=1)return ;
  m=2*n-1;
  HT=new HTNode[m+1];
  for(i=1;i<=m;++i)    //将1-m号单元的父结点、左孩子、右孩子的下标都初始化为0
   {
    
    
     HT[i].parent=0;
     HT[i}.lchild=0;
     HT[i}.rchild=0;
   }
  for(i=1;i<=n;++i)  //输入前n个结点的权值
   {
    
    
      cin>>HT[i].weight;
   }
  for(i=n+1;i<=m;++i)
  {
    
     //通过n-1次的选择、删除、合并来创建哈夫曼树
    Select(HT,i-1,s1,s2);
    //在HT[k](1<=k<=i-1)中选择两个其双亲域为0且权最小的结点,并返回他们在HT中的序号s1和s2
    HT[s1}.parent=i;
    HT[s2}.parent=i;
    //得到新结点i,从森林中删除s1,s2,将s1和s2的双亲域由0改为1
    HT[i].lchild=s1;   //s1作为i的左结点
    HT[i}.rchild=s2;  //s2作为i的右结点
    HT[i].weight=HT[s1].weight+HT[s2].weight;  //i的权值为左右孩子权值之和
  }

3、ハフマン符号化

ツリーの左側のブランチを0としてマークし、右側のブランチを1としてマークします; (左0と右1)
ここに画像の説明を挿入

正しい ハフマン符号化
5 0 0 0 0
3 0 0 0 1
11 0 0 1
23 0 1
29 1 0
14 1 1 1
7 1 1 0 0
8 1 1 0 1

第四に、ハフマンツリーの作成

要件:
1。キーボードからnとn文字の確率を入力します。
例:通信中の特定のシステムにはn種類の文字しか表示されないことが知られており、それらの確率はそれぞれ0.05、0.29、0.07、0.08、0.14、0.23、0.03、0.11です。作成するハフマンコードを設計してみてください。ハフマンツリー。
2.シーケンシャルストレージを使用します。

#include<iostream>
using namespace std;
//哈夫曼树的存储结构
typedef struct {
    
    
	int weight;  //结点的权重
	int parent, lchild, rchild;  //结点的双亲、左孩子、右孩子的下标
}HTNode,*HuffmanTree;
//封装两个最小结点
typedef struct {
    
    
	int s1;
	int s2;
}MIN;
//选择双亲为0且结点权值最小的两个结点
MIN Select(HuffmanTree HT, int n)
{
    
    
	int min, secmin,s1,s2;
	min = 10000;
	secmin = 10000;
	MIN code;
	s1 = 1; s2 = 1;
	for (int i = 1; i <= n; i++)
	{
    
    
		if (HT[i].parent == 0 && (HT[i].weight<min))
		{
    
    
			min = HT[i].weight;
			s1 = i;
		}
	}
	for (int i = 1; i <= n; i++)
	{
    
    
		if (HT[i].parent == 0 && (HT[i].weight<secmin) && (i != s1))
		{
    
    
			secmin = HT[i].weight;
			s2 = i;
		}
	}
	code.s1 = s1;
	code.s2 = s2;
	return code;

}
//创造哈夫曼树
void CreateHuffmanTree(HuffmanTree &HT, int num)
{
    
    
	
	int m;
	m = 2 * num - 1;
	HT = new HTNode[m + 1];
	for (int i = 1; i <= m; i++)
	{
    
    
		HT[i].parent = 0;
		HT[i].lchild = 0;
		HT[i].rchild = 0;
	}
	cout << "请输入每个叶子结点的权值:" << endl;
	for (int i = 1; i <= num; i++)
	{
    
    
		cin >> HT[i].weight;
	}
	
	for (int i = num + 1; i <= m; i++)
	{
    
    
		MIN min;
		min=Select(HT,i-1);
		HT[min.s1].parent = i;
		HT[min.s2].parent = i;
		HT[i].lchild = min.s1;
		HT[i].rchild = min.s2;
		HT[i].weight = HT[min.s1].weight + HT[min.s2].weight;
	}
	//输出哈夫曼树存储结构的末态
	for (int i = 1; i <= m; i++)
	{
    
    
		cout << "结点序号 " << i << " 权重 " << HT[i].weight << " parent " << HT[i].parent << " lchild " << HT[i].lchild << " rchild " << HT[i].rchild << endl;
	}

}

int main()
{
    
    
	cout << "开始创建哈夫曼树" << endl;
	int num;  //结点的个数
	cout << "请输入哈夫曼树叶子结点的个数:";
	cin >> num;
	//创造哈夫曼树
	HuffmanTree HT;
	CreateHuffmanTree(HT, num);
	return 0;
}

おすすめ

転載: blog.csdn.net/gets_s/article/details/106160072