}
voidHuffmanCode(HTNode*root)
{
//以前序周游的思想编码
root->code="";//root的Huffman编码
stackaStack;//存储未访问元素的栈
HTNode*temp=root;
aStack.push(NULL);//栈底监视哨
while(temp)
{
if(NULL!
=temp->right)
{
temp->right->code=temp->code+"1";
aStack.push(temp->right);
}
if(NULL!
=temp->left)
{
temp->left->code=temp->code+"0";
temp=temp->left;
}
else//左子树访问完毕,转向访问右子树
{
temp=aStack.top();
aStack.pop();
}
}//while
}//Huffman编码函数
public:
MyHuffmanTree(HTNode*r)
{
root=r;
HuffmanCode(root);
}//构造函数
MyHuffmanTree(){DeleteTree(root);}//析构函数
voidDeleteTree(HTNode*root)
{
if(NULL!
=root)
{
DeleteTree(root->left);
DeleteTree(root->right);
}
deleteroot;
}//销毁树函数
voidInOrder(HTNode*root)
{
if(NULL!
=root)
{
InOrder(root->left);
visit(root);
InOrder(root->right);
}
}//中序周游
HTNode*Root(){returnroot;}//返回跟结点函数
}
main文件:
#include"HuffmanTree.h"
#include"MinHeap.h"
#include
#include
#include
usingnamespacestd;
intmain()
{
intf[128]={0};//频率表
charc;//读入字符
//打开文件
ifstreamfin("input.txt");
if(!
fin)
{cout<<"cannotopeninput.txt";return0;}
//从文件中读入数据
while(!
fin.eof())
{
fin>>c;
f[c]++;
}
MinHeapheap(128);
HTNode*p;//建堆用指针
HTNode*first,*second,*pa;
for(inti=0;i<128;i++)
{
if(0!
=f[i])
{
p=newHTNode(i,f[i]);
heap.insert(p);
}//if
}//for,建最小堆
heap.display();
while(1!
=heap.GetCurrentSize())//n-1次合并
{
first=heap.min();//取得最小的一个结点
heap.remove(0);
second=heap.min();//取得第二小的一个结点
heap.remove(0);
pa=newHTNode(0,first->weight+second->weight);
pa->left=first;
pa->right=second;
heap.insert(pa);
}
pa=heap.min();
heap.remove(0);
MyHuffmanTreemht(pa);
mht.InOrder(mht.Root());
return0;
}
最小堆MinHeap.h文件:
#include
usingnamespacestd;
template
classMinHeap
{
private:
T*heapArray;//存放堆数据的数组
intCurrentSize;//当前堆中的元素数目
intMaxSize;//最大元素数目
voidswap(intpos_x,intpos_y)//交换位置xy的元素的函数
{
if(pos_x<0||pos_y<0)return;
Ttemp;
temp=heapArray[pos_x];
heapArray[pos_x]=heapArray[pos_y];
heapArray[pos_y]=temp;
}
public:
MinHeap(constintsize)//构造函数,size为堆的最大元素数目
{
if(size<=0)return;
CurrentSize=0;
MaxSize=size;
heapArray=newT[MaxSize];
}
MinHeap(){delete[]heapArray;}//析构函数
boolisEmpty()//判断堆是否为空的函数
{return((CurrentSize==0)?
true:
false);}
boolisLeaf(intpos)//判断是否是叶子结点的函数
{return(pos>=CurrentSize/2)&&(posintleftchild(intpos)//返回左孩子位置的函数
{return(2*pos+1);}
intrightchild(intpos)//返回右孩子位置的函数
{return(2*pos+2);}
intParent(intpos)//返回父结点位置的函数
{return((pos-1)/2);}
intPos(Tvalue)//找出值为value的元素在堆中位置的函数
{
for(inti=0;i{
if(heapArray[i]==value)
returni;
}
return-1;
}//pos
boolinsert(constT&newNode)//向堆中插入新元素newNode
{
//判断堆是否已满
if(CurrentSize==MaxSize)//堆已满
{cout<<"堆已满"<//堆未满
heapArray[CurrentSize]=newNode;//新元素newNode放到堆的末尾
SiftUp(CurrentSize);//向上调整
CurrentSize++;//堆的当前元素数加1
returntrue;
}//insert
boolremove(intpos)//删除给定下标的元素
{//判断下标是否越界
if((pos<0)||(pos>=CurrentSize))
returnfalse;
//下标未越界
heapArray[pos]=heapArray[--CurrentSize];//用最后的元素值代替被删除的元素
if(pos==0)
SiftDown(pos);
if(heapArray[Parent(pos)]>heapArray[pos])
SiftUp(pos);
elseSiftDown(pos);
returntrue;
}//remove
T&min()//返回最小值元素
{returnheapArray[0];}
voidSiftUp(intpos)//从pos开始向上调整
{
inttemppos=pos;
Ttemp=heapArray[temppos];
while((temppos>0)&&(heapArray[Parent(temppos)]>temp))
{
heapArray[temppos]=heapArray[Parent(temppos)];
temppos=Parent(temppos);
}
heapArray[temppos]=temp;
}//SiftUp
voidSiftDown(intpos)//从pos开始向下调整
{
inti=pos;//标识父结点
intj=leftchild(i);//用于记录关键值较小的子结点
Ttemp=heapArray[i];//记录父结点元素值
while(j{
if((jheapArray[j+1]))//若有右子结点且小于左子结点
j++;//j指向小的右子结点
if(temp>heapArray[j])//若父结点的值大于子结点的值则交换
{
heapArray[i]=heapArray[j];
i=j;
j=leftchild(j);
}//if
elsebreak;//父结点<=子结点满足堆序跳出
}//while
heapArray[i]=temp;
}//SiftDown
voiddisplay()//显示堆中内容
{
inti;
for(i=0;i{
cout<}
}//display
T&RemoveMin()
{
if(CurrentSize==0){
cout<<"CannotDelete";
exit
(1);}//if
else
{
swap(0,--CurrentSize);
if(CurrentSize>1)
SiftDown(0);
returnheapArray[CurrentSize];
}//else
}//RemoveMin
intGetCurrentSize()
{returnCurrentSize;
}}
程序运行结果:
输入:
246810
输出:
权:
13579
三、总结和分析
经过这次程序设计,我深刻的认识到,编写的程序不但要拿来使用,还要给别人查看,以便代码的维护。
所以代码编写的风格尽量规范,清晰。
代码较为冗余,可读性较差,可以多添加一些提示语句以及注释。
在这次课程设计中我又进一步地了解了数据结构中算法的核心思想的重要性,懂得了一个程序地好坏关键在于算法是否优秀,一个好的优秀的算法可以使我们的程序更加完善,安全性更高以及有更高的效率。
这次设计中我发现了自己的许多不足,更深入的了解了数据结构的思想,明白了理论知识和实际操作编写程序是密不可分的。
同时,也明白了同学之间团结合作的重要性。
指导老师评语:
成绩评定:
指导老师签名:
基地指导老师签名:
年月日
教研室意见
教研室主任签章
年月日
学院意见
分管院长签章
年月日