美文网首页
构造霍夫曼编码

构造霍夫曼编码

作者: 云飞扬1 | 来源:发表于2020-09-22 18:15 被阅读0次
    class HuffmanTreeNode(val str: String) {
        //权重
        var weight = 0
        var left: HuffmanTreeNode? = null
        var right: HuffmanTreeNode? = null
        var parent: HuffmanTreeNode? = null
    
        fun setWeight(w: Int): HuffmanTreeNode {
            weight = w
            return this
        }
    }
    
    /**
     * 构造霍夫曼树
     *
     * @param list 节点列表
     * @return 霍夫曼节点
     */
    fun buildHuffmanTree(list: List<HuffmanTreeNode>): HuffmanTreeNode? {
        if (list.isEmpty())
            return null
        if (list.size == 1) {
            return list[0]
        }
        //构建小顶堆
        var array: Array<HuffmanTreeNode> = Array(list.size) { i -> list[i] }
        buildMinHeap(array)
    
        var size = array.size
        while (size > 1) {
            //取出最小的节点
            var min1 = getMinWeightNode(array, size)
            //取出最小的节点
            var min2 = getMinWeightNode(array, size - 1)
            //构造新的节点
            var newNode = HuffmanTreeNode("").setWeight(min1.weight + min2.weight)
            newNode.left = min1
            newNode.right = min2
            min1.parent = newNode
            min2.parent = newNode
            size--
            if (size == 1) {
                return newNode
            }
            //新的节点插入小顶堆
            insertNode(array, size - 1, newNode)
        }
        return null
    }
    
    /**
     * 根据权重构造小顶堆
     */
    fun buildMinHeap(array: Array<HuffmanTreeNode>) {
        for (i in array.size / 2 downTo 0) {
            var min = i
            while (min < array.size && (min * 2 + 1) < array.size) {
                var tmp = min
                var left = min * 2 + 1
                var right = left + 1
                if (left < array.size && array[min].weight > array[left].weight) {
                    min = left
                }
                if (right < array.size && array[min].weight > array[right].weight) {
                    min = right
                }
                if (tmp == min)
                    break
                else {
                    var t = array[tmp]
                    array[tmp] = array[min]
                    array[min] = t
                }
            }
        }
    }
    
    /**
     * 取出权重值最小的元素,即小顶堆堆顶元素,剩余的元素会重新堆化
     *
     * @param array 小顶堆数组
     * @param size 当前小顶堆数组元素的个数
     *
     * @return 最小的元素
     */
    fun getMinWeightNode(array: Array<HuffmanTreeNode>, size: Int): HuffmanTreeNode {
        var top = array[0]
        array[0] = array[size - 1]
        var i = 0
        while (i < size - 1) {
            var tmp = i
            var left = i * 2 + 1
            var right = left + 1
            if (left < size - 1 && array[i].weight > array[left].weight) {
                i = left
            }
            if (right < size - 1 && array[i].weight > array[right].weight) {
                i = right
            }
            if (tmp == i)
                break
            else {
                var t = array[tmp]
                array[tmp] = array[i]
                array[i] = t
            }
        }
        return top
    }
    
    /**
     * @param array 小顶堆数组
     * @param size 当前小顶堆数组元素个数
     * @param node 要插入的节点
     *
     * @return 插入节点后小顶堆元素个数
     */
    fun insertNode(array: Array<HuffmanTreeNode>, size: Int, node: HuffmanTreeNode): Int {
        array[size] = node
        var i = size
        while (i > 0) {
            var parent = (i - 1) / 2;
            if (array[parent].weight > array[i].weight) {
                var tmp = array[parent];
                array[parent] = array[i];
                array[i] = tmp;
                i = parent;
            } else {
                break;
            }
        }
        return size + 1
    }
    
    //获取霍夫曼编码
    fun getHuffmanCode(node: HuffmanTreeNode): String {
        var stack = Stack<String>()
        var curr = node
        while (curr.parent != null) {
            var p = curr.parent!!
            if (p.left == curr) {
                stack.push("0")
            } else {
                stack.push("1")
            }
            curr = p
        }
        var sb = StringBuilder()
        while (stack.isNotEmpty()) {
            sb.append(stack.pop())
        }
        return sb.toString()
    }
    
    fun main() {
    
        var a = HuffmanTreeNode("a").setWeight(450)
        var b = HuffmanTreeNode("b").setWeight(350)
        var c = HuffmanTreeNode("c").setWeight(90)
        var d = HuffmanTreeNode("d").setWeight(60)
        var e = HuffmanTreeNode("e").setWeight(30)
        var f = HuffmanTreeNode("f").setWeight(20)
    
        val nodeList = listOf(a, b, c, d, e, f)
        //构造霍夫曼树
        var root = buildHuffmanTree(nodeList)
    
        var map = mutableMapOf<String, String>()
        root?.let {
            map.put(a.str, getHuffmanCode(a))
            map.put(b.str, getHuffmanCode(b))
            map.put(c.str, getHuffmanCode(c))
            map.put(d.str, getHuffmanCode(d))
            map.put(e.str, getHuffmanCode(e))
            map.put(f.str, getHuffmanCode(f))
        }
    
        for (entry in map) {
            println("${entry.key}: ${entry.value}")
        }
    }
    

    最终结果如下:

    a: 0
    b: 11
    c: 100
    d: 1010
    e: 10111
    f: 10110
    

    相关文章

      网友评论

          本文标题:构造霍夫曼编码

          本文链接:https://www.haomeiwen.com/subject/ytvjektx.html