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