哈夫曼树构建

8 篇文章 0 订阅

哈夫曼树是带权值的树节点结构,且目标节点都存储在叶子节点上。下面使用Go实现哈夫曼树

哈弗曼树构建过程

  1. 将带权值的节点进行排序,形成有序的链表。
  2. 取出链表头两个节点,权值相加形成新节点,并加入上述链表中重新排序,两节点分别为构建为左右子树,新创建的节点为父节点。
  3. 重复步骤2直到链表节点为1退出构造

哈夫曼节点定义

type huffmannode struct {
	value  interface{}	//store the value of huffman tree node
	weight uint32	//store the weight of node
}

节点实现链表的比较以及打印接口

func (hmn *huffManNode) Print() {
	fmt.Printf("Value:%c Weight:%d\n", hmn.value, hmn.weight)
}

func (hmn *huffManNode) Cmp(h interface{}) int {
	if hmn1, ok := h.(*huffManNode); ok {
		if hmn.weight > hmn1.weight {
			return 1
		} else if hmn.weight == hmn1.weight {
			return 0
		} else {
			return -1
		}
	}

	return -2
}

实现过程中需要用到链表以及树作为辅助数据结构,链表定义可参考链表,树结构可以参考二叉树相关

创建哈夫曼树实现如下

func CreatHuffman(keys map[interface{}]uint32) *jlalgorithm.BinaryTree {
	var pRet *jlalgorithm.BinaryTree
	var pList *jlalgorithm.LinkList
	for key, value := range (keys) {
		pList = jlalgorithm.OrderInsert(pList, jlalgorithm.NewLinkList(&huffManNode{key, value}))
	}

	jlalgorithm.Dump(pList)
	for node := pList; node != nil; node = pList {
		node1, _ := node.Value.(*huffManNode) //Get First Node Of The Order LinkList
		if tmpTree1, ok := node1.value.(*jlalgorithm.BinaryTree); ok {
			pRet = tmpTree1 //Judge The Node Is Tree Node
		} else {
			pRet = jlalgorithm.NewBinaryTree(node1)
		}

		if node.GetNext() != nil {
			node2, _ := node.GetNext().Value.(*huffManNode) //Get The Second Node Of The Order LinkList
			tmpTree := jlalgorithm.NewBinaryTree(nil)
			tmpTree.AddLeft(pRet) //The Smaller Weight Node As The Left Child Node
			if tmpTree2, ok := node2.value.(*jlalgorithm.BinaryTree); ok {
				tmpTree.AddRight(tmpTree2)
			} else {
				tmpTree.AddRight(jlalgorithm.NewBinaryTree(node2))
			}

			//Create New Node Weight Is Sum Of The Two Node Weight
			newnode := jlalgorithm.NewLinkList(&huffManNode{tmpTree, node1.weight + node2.weight})
			pList = jlalgorithm.OrderInsert(node.GetNext().GetNext(), newnode)
		} else {
			break
		}
	}

	//Handle Only One Node Of Huffman
	if nil != pRet && nil != pRet.Value {
		tmp := jlalgorithm.NewBinaryTree(nil)
		tmp.AddLeft(pRet)
		pRet = tmp
	}

	return pRet
}

获取哈夫曼编码

遍历哈夫曼树,左节点路径为0,右节点路径为1,找到目标节点所走的路径即为哈夫曼编码。

func GetHuffmanCode(key interface{}, pRoot *jlalgorithm.BinaryTree) ([]byte, bool) {
	if pRoot != nil {
		ret := make([]byte, 0)
		if pRoot.GetLeft() != nil {
			if node, ok := pRoot.GetLeft().Value.(*huffManNode); ok {
				if node.value == key {
					return append(ret, 0), true
				}
			} else {
				if result, ok := GetHuffmanCode(key, pRoot.GetLeft()); ok {
					ret = append(ret, 0)
					return append(ret, result...), true
				}
			}
		}

		if pRoot.GetRight() != nil {
			if node, ok := pRoot.GetRight().Value.(*huffManNode); ok {
				if node.value == key {
					return append(ret, 1), true
				}
			} else {
				if result, ok := GetHuffmanCode(key, pRoot.GetRight()); ok {
					ret = append(ret, 1)
					return append(ret, result...), true
				}
			}
		}
	}

	return nil, false
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值