65,173
社区成员




#pragma once
#ifndef HUFFMAN_H
#define HUFFMAN_H
#include <iostream>
using namespace std;
//节点类(抽象类)
template <typename E>
class HuffNode
{
public:
virtual ~HuffNode() {}
virtual int weight() = 0;
virtual bool isLeaf() = 0;
};
//叶节点类(继承自节点类)
template<typename E>
class LeafNode :public HuffNode<E>
{
private:
E it;
int wgt;
public:
//构造叶节点
LeafNode(const E& val, int freq)
{
it = val;
wgt = freq;
}
//返回该叶节点的权值
int weight()
{
return wgt;
}
//返回节点的值
E val()
{
return it;
}
//判断是否是叶节点
bool isLeaf()
{
return true;
}
};
//内部节点类(继承自节点类)
template <typename E>
class IntlNode :public HuffNode<E>
{
private:
HuffNode<E>* lc;
HuffNode<E>* rc;
int wgt;
public:
//构造内部节点
IntlNode(HuffNode<E>* l, HuffNode<E>* r)
{
wgt l->weight() + r->weight();
lc = l;
rc = r;
}
//返回节点的权值
int weight()
{
return wgt;
}
//判断节点是不是叶子节点
bool isLeaf()
{
return false;
}
//返回左子树
HuffNode<E>* left() const
{
return lc;
}
//设置左子树
void setLeft(HuffNode<E>* b)
{
lc = (HuffNode<E>*)b;
}
//返回右子树
HuffNode<E>* right() const
{
return rc;
}
//设置右子树
void setRight(HuffNode<E>* b)
{
rc = (HuffNode<E>*)b;
}
};
//Huffman树
template <typename E>
class HuffTree {
private:
HuffNode<E>* Root;
public:
//构建Huffman数(叶节点构造)
HuffTree(E& val, int freq)
{
Root = new LeafNode<E>(val, freq);
}
//构建Huffman数(内部节点构造)
HuffTree(HuffTree<E>* l, HuffTree<E>* r)
{
Root = new IntlNode<E>(l->root(), r->root());
}
//析构,释放空间?
~HuffTree()
{
if (root == NULL)
{
return;
}
else if (root->isLeaf())
{
delete root;
}
else {
IntlNode<E>* rt = (IntlNode<E>*)root;
Traverse(rt->left());
Traverse(rt->right());
delete root;
}
}
//返回根节点
HuffNode<E>* root()
{
return Root;
}
//返回根节点的权值
int weight()
{
return root->weight();
}
//遍历Huffman节点(中序遍历)
void Traverse(HuffNode<E>* root)
{
if (root == NULL)
{
return;
}
else if (root->isLeaf())
{
cout << "Leaf:"root->weight() << endl;
}
else {
IntlNode<E>* rt = (IntlNode<E>*)root;
Traverse(rt->left());
cout << "Internal:" << rt->weight() << endl;
Traverse(rt->right());
}
}
};
//最小堆的实现
template<typename E>
class heap {
private:
HuffTree<E>** Heap;
int maxsize;
int n;
//将左右子树是堆的二叉树变成堆
void siftdown(int pos)
{
while (!isLeaf(pos))
{
int j = leftchild(pos);
int rc = rightchild(pos);
if ((rc < n) && (Heap[j]->weight() > Heap[rc]->weight()))
{
j = rc;
}
if (Heap[j]->weight() > Heap[pos]->weight())
{
return;
}
swap(Heap, pos, j);
}
}
public:
//交换堆中处于frist和second位置的元素
void swap(HuffTree<E>** array, int first, int second)
{
HuffTree* Temp = array[first];
array[first] = array[second];
array[second] = temp;
}
//建堆
void buildHeap()
{
for (int i = n / 2 - 1; i >= 0; i--)
siftdown(i);
}
//堆得构造函数
heap(HuffTree<E>** h, int max, int num)
{
Heap = h;
maxsize = max;
n = num;
buildHeap();
}
//返回堆得大小
int size() const
{
return n;
}
//判断该位置的堆是不是叶节点
bool isLeaf(int pos) const
{
return (pos >= n / 2) && (pos < n);
}
//返回堆的左子孩子(传入位置)
int leftchild(int pos) const
{
return pos * 2 + 1;
}
//返回堆的右子孩子(传入位置)
int rightchild(int pos) const
{
return pos * 2 + 2;
}
//返回堆得父孩子(传入位置)
int parent(int pos) const
{
return (pos - 1) / 2;
}
//将it插入堆中
void insert(HuffTree* it)
{
int curr = n++;
Heap[curr] = it;
while ((curr! = 0) && (Heap[parent(curr)]->weight() > Heap[curr]->weight()))
{
swap(Heap, curr, parent(curr));
curr = parent(curr);
}
}
//移除堆中的第一个元素,返回该元素值
HuffTree<E>* removefirst()
{
Assert(n > 0, "Heap is empty");
swap(Heap, 0, --n);
if (n != 0)
{
siftdown(0);
}
return Heap[n];
}
//移除指定位置的元素
E remove(int pos)
{
Assert((pos > 0) && (pos < n), "Bad position");
if (pos == (n - 1))
{
n--;
}
else
{
swap(Heap, pos, --n);
while ((pos != 0) && (Heap[parent(pos)]->weight() > Heap[pos]->weight()))
{
swap(Heap, pos, parent(pos));
pos = parent(pos);
}
if (n != 0)
siftdown(pos);
}
return Heap[n];
}
};
//建树
template<typename E>HuffTree<E>*
buildHuff(HuffTree<E>** TreeArray, int count)
{
//用给定的数组建堆
heap<HuffTree<E>*, minTreeComp>*forest =
new heap<HuffTree<E>*, minTreeComp>(TreeArray, count, count);
HuffTree<char>* temp1, *temp2, *temp3 = NULL;
//利用堆建树
while (forest->size() > 1)
{
temp1 = forest->removefirst();
temp2 = forest->removefirst();
temp3 = new HuffTree<E>(temp1, temp2);
forest->insert(temp3); //put new tree back on list
delete temp1;
delete temp2;
}
return temp3;
}
#endif