【Lua】哈夫曼树构造算法的分析与实现

哈夫曼树构造算法分析

1、哈夫曼树中权重越大的叶子离根越近,采用贪心算法构造哈夫曼树,首先选中权重值小的叶子结点进行构造
2、步骤

  1. 构造森林全是根:根据n个给定结点的权重值{W1, W2…Wn}构成 n 颗二叉树的森林F = {T1, T2…Tn},其中 Ti 只有一个带权重为 Wi 的根结点
  2. 选用两小造新树:在F中选取两颗跟结点权重值最小的两颗树作为左右树构成新二叉树,此二叉树的权重值为左右树权重值之和
  3. 删除两小添新树:在F中删除这两颗树,同时将新的到的二叉树添加到森林中
  4. 重复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

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值