构造一棵哈夫曼树

Posted _Camille

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了构造一棵哈夫曼树相关的知识,希望对你有一定的参考价值。

一、huffman树是什么?

树的路径长度:
huffman说过:“从树中的一个节点到另一个节点之间的分支构成两个节点之间的路径,路径上的分支数目称为路径长度;数的路径长度就是树根到每一个节点的路径长度之和。”

树的带权路径长度:
huffman又说:“如果考虑到节点带权值,那么节点带权的路径长度为该节点到树根的路径长度与权值的乘积,因此树的带权路径长度为树中所有叶子节点的带权路径长度和。”

huffman树 == 带权路径长度最小的二叉树

如何构造huffman树?

从前面我们已经知道huffman树就是带权路径长度最短的树,因此构造huffman树只需要让权值较大的节点尽量靠近树根。
1.由给定的n个权值构造n棵只有根节点的二叉树森林;

2.在森林中选取两颗节点权值最小的二叉树,作为左右子树构造一棵新二叉树,新二叉树根节点的权值为左右子树节点的权值之和,并且在森林中删除你选取的两棵树,将新构造的树加入森林。然后重复上述直到森林仅剩下一棵树为止。

使用堆作为保存这棵huffman树的数据结构,why?因为每次要取最小的两个节点,因此这里我们使用优先级队列(底层是堆)priority_queue,比较方式采用大于greater比较,小根堆。
根据上述我们可以写出如下的赫夫曼树:

#ifndef _HUFFMANTREE_HPP_
#define _HUFFMANTREE_HPP_

#include<iostream>
#include<vector>
#include<queue>
using namespace std;

template<class W>
struct HuffmanTreeNode

	HuffmanTreeNode<W>* left;
	HuffmanTreeNode<W>* right;
	W weight;

	HuffmanTreeNode(const W& w = W())
		:left(nullptr),
		right(nullptr),
		weight(w)
	 
;
//实现对应于赫夫曼节点的greater()仿函数
template<class W>
struct Com

	typedef HuffmanTreeNode<W> Node;
	bool operator()(const Node* left, const Node* right)
	
		return left->weight > right->weight;
	
;

template<class W>
class HuffmanTree

	typedef HuffmanTreeNode<W> Node;
public:
	HuffmanTree() :root(nullptr)
	
	~HuffmanTree()
	
		Destroy(root);
	

	void CreateHuffmanTree(vector<W>& arr, size_t size)
	
		//小堆
		/*std::priority_queue<Node*, vector<Node*>, greater<Node*>> q;*/
		/*此处会出现问题,因为会按照地址去比较而不是权值,因此自己实现一个
		仿函数来实现用权值去比较*/
		std::priority_queue<Node*, vector<Node*>, Com<W>> q;
		//1.先使用所给的权值创建只有根节点的二叉树森林
		for (size_t i = 0; i < size; ++i)
		
			q.push(new Node(arr[i]));
		

		//2.从森林中挑选两个权值最小的树并将其合并,直到剩一棵树
		while (q.size() > 1)
		
			Node* left = q.top();
			q.pop();
			Node* right = q.top();
			q.pop();

			//将left和right作为新节点的左右子树,新节点权值=左右之和;
			Node* New_Node = new Node(left->weight + right->weight);
			New_Node->left = left;
			New_Node->right = right;

			//把新的树插入到堆中;
			q.push(New_Node);
		
		root = q.top();
	

	void Destroy(Node*& proot)
	
		if (proot)
		
			Destroy(proot->left);
			Destroy(proot->left);
			delete proot;
			proot = nullptr;
		
	
private:
	Node* root;
;


void test()

	vector<int>ar 3, 1, 7, 5 ;
	HuffmanTree<int> t;
	t.CreateHuffmanTree(ar, ar.size());



#endif /* _HUFFMANTREE_HPP_ */

以上是关于构造一棵哈夫曼树的主要内容,如果未能解决你的问题,请参考以下文章

构造一棵哈夫曼树

构造一棵哈夫曼树

如何构造哈夫曼树

构造哈夫曼树

已知权值集合 如何求其构造的哈夫曼树中带权路径长度之和 只求过程 急急急

Kruskal算法和Prim算法构造它的一棵最小代价生成树的过程