哈夫曼树构建

哈夫曼树是带权值的树节点结构,且目标节点都存储在叶子节点上。下面使用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
}

 

发布了58 篇原创文章 · 获赞 8 · 访问量 2万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章