#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;
}
Huffman树的基本操作
最新推荐文章于 2023-05-16 20:44:16 发布