实现哈弗曼树(后续实现哈弗曼编码)
1. MinHeap.h
/**************** MinHeap.h **********************/
#include <iostream>
using namespace std;
#define FALSE 0
#define TRUE 1
template <class T>
class MinHeap //最小堆类定义
{
private:
T* heapArray; //存放堆数据的数组
int CurrentSize; //当前堆中元素数目
int MaxSize; //堆所能容纳的最大元素数目
void swap(int pos_x, int pos_y); //交换位置x和y的元素
void BuildHeap(); //建堆
public:
MinHeap(const int n); //构造函数,n表示初始化堆的最大元素数目
virtual ~MinHeap()
{
delete []heapArray;
}; //析构函数
bool isLeaf(int pos) const; //如果是叶结点,返回TRUE
int leftchild(int pos) const; //返回左孩子位置
int rightchild(int pos) const; //返回右孩子位置
int parent(int pos) const; //返回父结点位置
bool Remove(int pos, T& node); //删除给定下标的元素
bool Insert(const T& newNode); //向堆中插入新元素newNode
T& RemoveMin(); //从堆顶删除最小值
void SiftUp(int position); //从position向上开始调整,使序列成为堆
void SiftDown(int left); //筛选法函数,参数left表示开始处理的数组下标
};
template<class T>
MinHeap<T>::MinHeap(const int n)
{
if(n <= 0)
return;
CurrentSize = 0;
MaxSize = n; //初始化堆容量为n
heapArray = new T[MaxSize]; //创建堆空间
//此处进行堆元素的赋值工作
BuildHeap();
}
template<class T>
bool MinHeap<T>::isLeaf(int pos) const
{
return (pos >= CurrentSize/2) && (pos < CurrentSize);
}
template<class T>
void MinHeap<T>::BuildHeap()
{
for (int i = CurrentSize/2-1; i >= 0; i--) //反复调用筛选函数
SiftDown(i);
}
template<class T>
int MinHeap<T>::leftchild(int pos) const
{
return 2*pos + 1; //返回左孩子位置
}
template<class T>
int MinHeap<T>::rightchild(int pos) const
{
return 2*pos + 2; //返回右孩子位置
}
template<class T>
int MinHeap<T>::parent(int pos) const
{
return (pos-1)/2; //返回父结点位置
}
template <class T>
bool MinHeap<T>::Insert(const T& newNode) //向堆中插入新元素newNode
{
if(CurrentSize == MaxSize) //堆空间已经满
return FALSE;
heapArray[CurrentSize] = newNode;
SiftUp(CurrentSize); //向上调整
CurrentSize++;
return TRUE;
}
template<class T>
void MinHeap<T>::SiftUp(int position) //从position向上开始调整,使序列成为堆
{
int temppos = position;
T temp = heapArray[temppos];
while ((temppos>0) && (heapArray[parent(temppos)]>temp))
{
heapArray[temppos] = heapArray[parent(temppos)];
temppos = parent(temppos);
}
heapArray[temppos] = temp;
}
template<class T>
void MinHeap<T>::swap(int pos_x, int pos_y) //交换位置x和y的元素
{
T temp = heapArray[pos_x];
heapArray[pos_x] = heapArray[pos_y];
heapArray[pos_y] = temp;
}
template<class T>
T& MinHeap<T>::RemoveMin() //从堆顶删除最小值
{
if (CurrentSize == 0)
{
cout<< "Can't Delete" <<endl;
// exit(0);
}
else
{
swap(0,--CurrentSize); //交换堆顶和最后一个元素
if(CurrentSize>1)
SiftDown(0); //从堆顶开始筛选
return heapArray[CurrentSize];
}
}
template<class T>
bool MinHeap<T>::Remove(int pos, T& node) // 删除给定下标的元素
{
if((pos < 0) || (pos >= CurrentSize))
return false;
T temp = heapArray[pos];
heapArray[pos] = heapArray[--CurrentSize]; //指定元素置于最后
if (pos != 0 && heapArray[parent(pos)] > heapArray[pos])
SiftUp(pos); // 当前元素小于父结点,需要上升调整
else
SiftDown(pos); // 当前元素大于父结点,向下筛
node = temp;
return true;
}
template <class T>
void MinHeap<T>::SiftDown(int left)
{
int i = left; //标识父结点
int j = leftchild (i); //标识关键值较小的子结点
T temp = heapArray[i]; //保存父结点
while (j < CurrentSize) //过筛
{
if((j < CurrentSize-1) && (heapArray[j] > heapArray[j + 1]))
j++; //j指向右子结点
if (temp>heapArray[j])
{
heapArray[i] = heapArray[j];
i = j;
j = leftchild(j); //向下继续
}
else break;
}
heapArray[i] = temp;
}
2. 哈弗曼树类
#include <iostream>
#include "MinHeap.h"
using namespace std;
template <class T> class HuffmanTree;
template <class T>
class HuffmanTreeNode
{
friend class HuffmanTree<T>;
private:
T info;
HuffmanTreeNode<T> *parent;
HuffmanTreeNode<T> *left;
HuffmanTreeNode<T> *right;
public:
HuffmanTreeNode() {};
HuffmanTreeNode<T> *leftchild()
{
return left;
};
HuffmanTreeNode<T> *rightchild()
{
return right;
};
bool operator > (HuffmanTreeNode<T> &HN)
{
return info > HN.info;
}; // 注意要重载运算符
bool operator < (HuffmanTreeNode<T> &HN)
{
return info < HN.info;
};
bool operator == (HuffmanTreeNode<T> &HN)
{
return info == HN.info;
};
};
template <class T>
class HuffmanTree
{
private:
HuffmanTreeNode<T>* root; //Huffman树的树根
//把ht1和ht2为根的Huffman子树合并成一棵以parent为根的二叉树
void MergeTree ( HuffmanTreeNode<T> &ht1, HuffmanTreeNode<T> &ht2, HuffmanTreeNode<T>* parent);
void DeleteTree(HuffmanTreeNode<T>* root); //删除Huffman树或其子树
public:
//构造Huffman树,weight是存储权值的数组,n是数组长度
HuffmanTree(T weight[],int n);
virtual ~HuffmanTree()
{
DeleteTree(root);
}; //析构函数
void InOrder(HuffmanTreeNode<T> *root); //中序周游
HuffmanTreeNode<T> *GetRoot()
{
return root;
};
};
template<class T>
HuffmanTree<T>::HuffmanTree(T weight[], int n)
{
MinHeap< HuffmanTreeNode<T> > heap(n); //定义最小值堆
HuffmanTreeNode<T> *parent, firstchild, secondchild;
HuffmanTreeNode<T>* NodeList = new HuffmanTreeNode<T>[n];
for(int i = 0; i < n; i++) //初始化
{
NodeList[i].info = weight[i];
NodeList[i].parent = NodeList[i].left = NodeList[i].right = NULL;
heap.Insert(NodeList[i]); //向堆中添加元素
}
for(int i = 0; i < n-1; i++) //通过n-1次合并建立Huffman树
{
parent = new HuffmanTreeNode<T>;
firstchild = heap.RemoveMin(); //选择权值最小的结点
secondchild = heap.RemoveMin(); //选择权值次小的结点
MergeTree(firstchild, secondchild, parent); //合并权值最小的两棵树
heap.Insert(*parent); //把parent插入到堆中去
root = parent; //建立根结点
}
delete []NodeList;
}
template <class T>
void HuffmanTree<T>::DeleteTree(HuffmanTreeNode<T> *root)
{
if (root)
{
DeleteTree(root->left);
DeleteTree(root->right);
delete root;
}
}
template <class T>
void HuffmanTree<T>::InOrder(HuffmanTreeNode<T> *root) //中序周游
{
if (root)
{
InOrder(root->left);
cout << root->info << " ";
InOrder(root->right);
}
}
template <class T>
void HuffmanTree<T>::MergeTree(HuffmanTreeNode<T> &ht1, HuffmanTreeNode<T> &ht2, HuffmanTreeNode<T> *parent)
{
HuffmanTreeNode<T> *l = new HuffmanTreeNode<T>();
HuffmanTreeNode<T> *r = new HuffmanTreeNode<T>();
*l = ht1; // 不能写为l = &ht1,注意地址引用,开辟的是新空间,或者应用拷贝构造函数,只是有些麻烦
*r = ht2;
parent->parent = NULL;
parent->left = l;
parent->right = r;
parent->info = ht1.info + ht2.info;
ht1.parent = ht2.parent = parent; // 指向父节点
}
int main()
{
int weight[] = {6,2,3,4}; //权值
HuffmanTree<int> a(weight,4); //图5.19 Huffman树
cout<< "HuffmanTree is constructed. " << endl;
cout<< "中序周游: " << endl;
a.InOrder(a.GetRoot()); //中序周游,结果:6 15 4 9 2 5 3
return 0;
}