哈夫曼树构造算法分析
1、哈夫曼树中权重越大的叶子离根越近,采用贪心算法构造哈夫曼树,首先选中权重值小的叶子结点进行构造
2、步骤
- 构造森林全是根:根据n个给定结点的权重值{W1, W2…Wn}构成 n 颗二叉树的森林F = {T1, T2…Tn},其中 Ti 只有一个带权重为 Wi 的根结点
- 选用两小造新树:在F中选取两颗跟结点权重值最小的两颗树作为左右树构成新二叉树,此二叉树的权重值为左右树权重值之和
- 删除两小添新树:在F中删除这两颗树,同时将新的到的二叉树添加到森林中
- 重复23剩下单根:重复2、3步骤知道森林中只有一颗树位置,此树即为哈夫曼树
哈夫曼树构造算法实现
--构造化哈夫曼树(n个初始结点)
function HuffmanTree:CreateHuffmanTree(n)
--哈夫曼树数组
local array = {}
--数组最大长度,array[m]为根结点
local m = 2 * n - 1
--初始化哈夫曼树
for i = 1, m do
local HFNode = HuffmanTreeNode.New()
HFNode.lch, HFNode.rch, HFNode.parent = 0, 0, 0
array[i] = HFNode
end
--设置权重(看需求,可以传值之类的,为了方便我使用随机数)
for i = 1, n do
array[i].weight = math.random(1, 10)
end
--构造哈夫曼树
for i = n + 1, m do
local idx1, idx2 = self:SeleceTwoMin(array)
array[idx1].parent = i
array[idx2].parent = i
--设置新结点的属性
array[i].lch = idx1
array[i].rch = idx2
array[i].weight = array[idx1].weight + array[idx2].weight
end
return array
end
--数组中权重最小两个的下标
function HuffmanTree:SeleceTwoMin(array)
local idx1, idx2 = 0, 0
local weight1, weight2 = 99, 99--初始权重值
for k, v in pairs(array) do
--双亲不为0(未构建)
if v.parent == 0 then
if v.weight ~= 0 and v.weight <= weight1 then
idx2 = idx1
weight2 = weight1
idx1 = k
weight1 = v.weight
elseif v.weight ~= 0 and v.weight <= weight2 then
idx2 = k
weight2 = v.weight
end
end
end
return idx1, idx2
end
--叶子结点构造
function HuffmanTreeNode:ctor()
--权重
self.weight = 0
--左孩子(数组中的下标)
self.lch = 0
--右孩子(数组中的下标)
self.rch = 0
--双亲(数组中的下标)
self.parent = 0
end
总结:
1、在算法中,初始有n个二叉树,要经过n-1次合并
2、结果n-1次合并会产生n-1个新结点,且具有左、右孩子
可见:哈夫曼树中共有n+n-1 = 2n-1 个结点,且其所有分支结点的度均不为1