1. 算法思想
构造哈夫曼树算法思路: 1.初始化HT[1…2n-1], lch=rch=parent=0.
2.输入n个叶子结点,置于HT[1…n]的weight(权值)。
3.进行n-1次合并,依次产生n-1个结点HT[i], i = n+1…2n-1; a) 在HT[1…i-1]中选两个未被选过(从parent==0的结点中选)的weight最小的两个结点HT[s1]和HT[s2], s1,s2为两个最小结点的下标 b) 修改HT[s1]和HT[s2]的parent值:HT[s1].patent=i, HT[s2].patent=i ; c) 修改新产生的的HT[i]; 1. HT[i].weight = HT[s1].weight + HT[s2].weight; 2. HT.lch = s1; HT[i].rch = s2;
2.完整代码
#include<iostream>
using namespace std
;
typedef struct{
int weight
;
int parent
, lch
, rch
;
}HTNode
, *HuffmanTree
;
int min(HuffmanTree t
, int i
)
{
int j
, m
;
unsigned int k
= UINT_MAX
;
for (j
= 1; j
<= i
; ++j
)
{
if ( t
[j
].weight
<= k
&& t
[j
].parent
== 0 )
{
k
= t
[j
].weight
;
m
= j
;
}
}
t
[m
].parent
= 1;
return m
;
}
void select(HuffmanTree t
, int i
, int &s1
, int &s2
)
{
int j
;
s1
= min(t
, i
);
s2
= min(t
, i
);
if (s1
> s2
)
{
j
= s1
;
s1
= s2
;
s2
= j
;
}
}
void CreatHuffmanTree(HuffmanTree HT
, int n
)
{
int m
, i
, s1
, s2
;
if (n
<= 1 )
return;
m
= 2 * n
- 1;
HT
= new HTNode
[m
+1];
for (i
= 1; i
<= m
; ++i
)
{
HT
[i
].lch
= 0;
HT
[i
].rch
= 0;
HT
[i
].parent
= 0;
}
for (i
= 1; i
<= n
; ++i
)
{
cin
>> HT
[i
].weight
;
}
for (i
= n
+1; i
<= m
; i
++)
{
select(HT
, i
-1, s1
, s2
);
HT
[s1
].parent
= i
;
HT
[s2
].parent
= i
;
HT
[i
].lch
= s1
;
HT
[i
].rch
= s2
;
HT
[i
].weight
= HT
[s1
].weight
+ HT
[s2
].weight
;
}
cout
<< "下标\t" << "权重\t" << "双亲\t" << "左孩子\t" << "右孩子" << endl
;
for (int j
= 1; j
< i
; j
++)
{
cout
<< j
<< "\t" << HT
[j
].weight
<< "\t" << HT
[j
].parent
<< "\t" << HT
[j
].lch
<< "\t" << HT
[j
].rch
<< endl
;
}
}
int main()
{
HuffmanTree HT
= NULL;
int n
;
cout
<< "请输入字符个数:" << endl
;
cin
>> n
;
cout
<< "请输入权值:" << endl
;
CreatHuffmanTree(HT
, n
);
return 0;
}
3.测试结果