哈夫曼樹構建

哈夫曼樹是帶權值的樹節點結構,且目標節點都存儲在葉子節點上。下面使用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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章