Huffman树的基本操作

#ifndef _HUFFMAN_
#define _HUFFMAN_

#include <deque>
#include <algorithm>

//哈夫曼:树的带权路径(WPL)最小的二叉树。用变长编码表进行编码,编码之后的字符串的平均长度、期望值降低,从而达到无损压缩数据的目的
template<typename T>
struct HuffmanNode
{
	HuffmanNode(T k, HuffmanNode<T>* l = nullptr, HuffmanNode<T>* r = nullptr) :key(k), lchild(l), rchild(r) {};
	~HuffmanNode();

	T key;
	HuffmanNode<T>* lchild;
	HuffmanNode<T>* rchild;
};

template<typename T>
class Huffman
{
public:
	Huffman();
	~Huffman();

	void preOrder();//前序遍历
	void inOrder();//中序遍历
	void postOrder();//后序遍历

	void print();//打印
	void create(T a[], int size);//创建哈夫曼数
	void destory();//销毁哈夫曼树

private:
	void preOrder(HuffmanNode<T>* pnode);
	void inOrder(HuffmanNode<T>* pnode);
	void postOrder(HuffmanNode<T>* pnode);
	void print(HuffmanNode<T>* pnode);
	void destory(HuffmanNode<T>* pnode);

private:
	HuffmanNode<T>* root;//哈夫曼数根节点
	//deque<HuffmanNode<int>*> forest;//森林(队列)
};

/* 哈夫曼树的构造步骤:
假设有n个权值,则构造出的哈夫曼树有n个叶子节点.n个权值记为{w1,w2,w3...wn},哈夫曼树的构造过程为:
1;将w1,w2,w3...wn看成具有n棵树的森林,每棵树仅有一个节点。
2.从森林中,选取两棵根节点权值最小的树,两棵树分别作为左子树与右子树,构建一棵新树。新树的权值等于左右子树权值之和。
3.从森林中删除两棵权值最小的树,将构建完成后的新树加入森林中。
4.重复2、3步骤,直到森林只剩一棵树为止。这棵树便是哈夫曼树。*/
template<typename T>
void Huffman<T>::create(T a[], int size)
{
	deque<HuffmanNode<T>*> forest;//森林(队列)
	for (int i = 0; i < size; i++)
	{
		HuffmanNode<T>* ptr = new HuffmanNode<T> (a[i], nullptr, nullptr);
		forest.push_back(ptr);
	}

	for (int i = 0; i < size-1; i++)
	{
		sort(forest.begin(), forest.end(), [](HuffmanNode<T>* a, HuffmanNode<T>* b){return a->key < b->key; });

		HuffmanNode<T>* newptr = new HuffmanNode<T> (forest[0]->key + forest[1]->key, forest[0], forest[1]);
		forest.push_back(newptr);
		forest.pop_front();
		forest.pop_front();
	}
	root = forest.front();
	forest.clear();
}

//遍历
template<typename T>
void Huffman<T>::print()
{
	return print(root);
}
template<typename T>
void Huffman<T>::print(HuffmanNode<T>* pnode)
{
	if (pnode != nullptr)
	{
		cout << "当前节点值为:" << pnode->key << " ";
		if (pnode->lchild != nullptr)
			cout << "其左节点值为:" << pnode->lchild->key << " ";
		else
			cout << "该节点无左孩子" << " ";
		if (pnode->rchild != nullptr)
			cout << "其右节点值为:" << pnode->rchild->key << " ";
		else
			cout << "该节点无右孩子" << " ";
		cout << endl;
		print(pnode->lchild);
		print(pnode->rchild);
	}
}

//前序遍历
template<typename T>
void Huffman<T>::preOrder()
{
	return preOrder(root);
}
template<typename T>
void Huffman<T>::preOrder(HuffmanNode<T>* pnode)
{
	if (pnode!=nullptr)
	{
		cout << pnode->key<<" ";
		preOrder(pnode->lchild);
		preOrder(pnode->rchild);
	}
}

//中序遍历
template<typename T>
void Huffman<T>::inOrder()
{
	return inOrder(root);
}
template<typename T>
void Huffman<T>::inOrder(HuffmanNode<T>* pnode)
{
	if (pnode != nullptr)
	{
		inOrder(pnode->lchild);
		cout << pnode->key << " ";
		inOrder(pnode->rchild);
	}
}

//后序遍历
template<typename T>
void Huffman<T>::postOrder()
{
	return postOrder(root);
}
template<typename T>
void Huffman<T>::postOrder(HuffmanNode<T>* pnode)
{
	if (pnode != nullptr)
	{
		postOrder(pnode->lchild);
		postOrder(pnode->rchild);
		cout << pnode->key << " ";
	}
}

//后序销毁哈夫曼树
template<typename T>
void Huffman<T>::destory()
{
	return destory(root);
}
template<typename T>
void Huffman<T>::destory(HuffmanNode<T>* pnode)
{
	if (pnode!=nullptr)
	{
		if (pnode->lchild != nullptr)
			destory(pnode->lchild);
		if (pnode->rchild != nullptr)
			destory(pnode->rchild);
		delete pnode;
		pnode = nullptr;
	}
}

template<typename T>
Huffman<T>::Huffman()
{
}
template<typename T>
Huffman<T>::~Huffman()
{
}

#endif


int main()
{
	Huffman<int> huffman;
	int a[] = { 10, 20, 30, 40 };
	huffman.create(a, 4);
	huffman.print();

	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/cat1992/article/details/76063148