HuffmanTree
一个Huffman编码的C++实现(这是我当助教的班的一个学生实现的,个人觉得做得还不错,所以分享出来)。
#include
#include
#include
#include
#define DN 26
#define SIZE 100
template
class MinHeap{
public:
MinHeap(int maxSize);
MinHeap(Type arr[],int n);
~MinHeap(){delete[]heap;}
int Insert(const Type &x);
int RemoveMin(Type &x);
Type DeleteMin();
int IsEmpty()const{return CurrentSize==0;}
int IsFull()const{return CurrentSize==MaxHeapSize;}
void MakeEmpty(){CurrentSize=0;}
private:
enum{DefaultSize=10};
Type *heap;
int CurrentSize;
int MaxHeapSize;
void FilterDown(const int start,const int end);
void FilterUp(int start);
};
template MinHeap::MinHeap(int maxSize){
MaxHeapSize=DefaultSize MinHeap::MinHeap(Type arr[],int n){//根据给定数组中的数据和大小,建立堆对象
MaxHeapSize=DefaultSize=0){//从下到上逐步扩大,形成堆
FilterDown(currentPos,CurrentSize-1);//从currentPos开始,到CurrentSize-1为止, 调整
currentPos--;
}
}
template int MinHeap::Insert(const Type&x){//在堆中插入新元素x
if(CurrentSize==MaxHeapSize){//堆满
cout<<"堆已满"< void MinHeap::FilterUp(int start){//从start开始,向上直到0,调整堆
int j=start,i=(j-1)/2;//i是j的双亲
Type temp=heap[j];
while(j>0){
if(heap[i].root->data.key<=temp.root->data.key)break;
else{heap[j]=heap[i];j=i;i=(i-1)/2;}
}
heap[j]=temp;
}
template void MinHeap::FilterDown(const int start,const int end){
int i=start,j=2*i+1;
Type temp=heap[i];
while(j<=end){
if(jdata.key>heap[j+1].root->data.key)j++;
if(temp.root->data.key<=heap[j].root->data.key)break;
else{
heap[i]=heap[j];
i=j;
j=2*j+1;
}
}
heap[i]=temp;
}
template int MinHeap::RemoveMin(Type &x){
if(!CurrentSize){
cout<<"Heap empty"< Type MinHeap::DeleteMin(){
if(!CurrentSize){
cout<<"Heap empty"<
struct NodeData{
Type symbol;//结点代表的符号
int key;//记录频数
char num;//结点编码
};
template class ExtBinTree;
template class Element{
friend class ExtBinTree;
friend class MinHeap >;
public:
Element(Type na='^',int f=0,char n='0'){
data.key=f;
data.symbol=na;
data.num=n;
parent=leftChild=rightChild=NULL;
}
private:
NodeData data;
Element*parent,*leftChild,*rightChild;
};
template class ExtBinTree{
friend class MinHeap >;
public:
ExtBinTree(int n=0,Type *s=NULL,Type *name=NULL,Element *l=NULL):
root(l),num(n),str(s){
na=new Type[n];
na=name;
fr=new int[n];
for(int i=0;i *bt1,ExtBinTree *bt2){
root->parent=NULL;
root->leftChild=(*bt1).root;
root->rightChild=(*bt2).root;
(*bt1).root->parent=(*bt2).root->parent=root;
(*bt1).root->data.num='0';
(*bt2).root->data.num='1';
root->data.key=(*bt1).root->data.key+(*bt2).root->data.key;
}
void HuffmanTree();//构造huffman树
Element* Find(Type item);//寻找结点的函数
char* Coding(Type item);//编码函数
void Fre();//计算字符频数的函数
void DeCoding(char s[]);//译码函数
int *GetFr(){return fr;}//返回字符出现的频数
double Entropy(int m);//求编码的平均码长
private:
Element *root;//扩充二叉树的根
int num;//输入的字符种类数
Type *str;//输入的字符串
Type *na;//存放各种字符
int *fr;//各种字符的频数
};
template
void ExtBinTree::HuffmanTree(){
int n(0),*f=new int[num];
char *s=new char[num];
for(int i=0;i *Node=new ExtBinTree[n];
for(i=0;i(s[i],f[i]);
MinHeap > hp(Node,n);
ExtBinTree first,second;
for(i=0;i;
Modify(&first,&second);//建新的根结点
hp.Insert(*this);//形成新树插入
}
}
template Element* ExtBinTree::Find(Type item){//寻找值为item的结点
Element*p=root,**s=new Element*[num+1];
int top=-1;
while(!(p==NULL&&top==-1)){
while(p!=NULL){
s[++top]=p;
p=p->leftChild;
}
if(top!=-1){
p=s[top--];
if(p->data.symbol==item)return p;
p=p->rightChild;
}
}
return NULL;
}
template char* ExtBinTree::Coding(Type item){
Element*p=Find(item);
if(p==NULL){
cerr<<"符号未找到!";
return NULL;
}
char *s=new char[num];
int i=-1;
while(p!=root){
s[++i]=p->data.num;
p=p->parent;
}
char *c=new char[i+2];
for(int j=0;j<=i;j++)
c[j]=s[i-j];
c[j]='\0';
return c;
}
template void ExtBinTree::DeCoding(char s[]){
int i=0;
Element*p=root;
while(s[i]!='\0'){
if(s[i]=='0'){
p=p->leftChild;
if(p->data.symbol!='^'){
cout<data.symbol;
p=root;
}
}
else{
p=p->rightChild;
if(p->data.symbol!='^'){
cout<data.symbol;
p=root;
}
}
i++;
}
}
template void ExtBinTree::Fre(){
int i=0;
while(*(str+i)!='\0'){
for(int j=0;j double ExtBinTree::Entropy(int m){//计算平均码长
double ent=0;
int n(0);
while(str[n]!='\0')n++;
if(m==0){
for(int i=0;i>s;
ExtBinTree h(DN,s,sym);
h.HuffmanTree();
int i=0;
cout<<"编码:\n";
while(s[i]!='\0'){
cout<
![Creative Commons License](http://i.creativecommons.org/l/by/2.5/cn/88x31.png)
本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名小橋流水(包含链接)。如您有任何疑问或者授权方面的协商,请给我发邮件。