4.7判定树和哈夫曼树
#include "stdafx.h"
#include <iostream.h>
#include <malloc.h>
int const ELEMENTCOUNT=5; //判断条件的个数,即初始根节点的数量
struct node
{
float wt; //权值
int parent,lchild,rchild; //双亲的下标,左子树下标,右子树下标
char data; //该节点的值,这是我加的,方便我在显示的时候验证是否正确
};
typedef node hftree[2*ELEMENTCOUNT-1]; //保存所有Huffman树的节点的数组,需要2N-1个元素
//count:初始根结点的数量,WT[]保存各节点的权值,tree为huffman树
//算法中我没有使用书上的变量名,说实话,书上变量名乱起(i,j,k,x,y,m,n.),我看明白了算法后才知道各个变量的意义.
void huffman(int count,float WT[],hftree & tree)
{
float minWT1=0,minWT2=0; //保存第一小和第二小权值
int minE1=0,minE2=0; //保存第一小和第二小的根的在数组中的下标
int i=0,j=0;
//初始化树
for(i=0;i<2*ELEMENTCOUNT-1;i++)
{
tree[i].parent=-1;
tree[i].lchild=-1;
tree[i].rchild=-1;
if (i<count)
{
tree[i].wt=WT[i];
}
else
{
tree[i].wt=0;
tree[i].data='N'; //N为新生成的结点
}
}
//开始生成huffman树
for(i=0;i<ELEMENTCOUNT-1;i++) //因为总结点数为2*ELEMENTCOUNT-1,而生成的新结点数为总结点数-初始根结点数,即:2*ELEMENTCOUNT-1-ELEMENTCOUNT=ELEMENTCOUNT-1
{
minWT1=minWT2=1; //1为最大权值
minE1=minE2=0;
//循环找到第1小和第2小的节点,并记住其权值
for(j=0;j<ELEMENTCOUNT+i;j++) //j<ELEMENTCOUNT+i意味着,每次都从0循环至上次新增的节点,用以寻找剩下的根结点
{
if (tree[j].parent==-1 && tree[j].wt<minWT1)
{
minE2=minE1;
minE1=j;
minWT2=minWT1;
minWT1=tree[j].wt;
}
else if (tree[j].parent==-1 && tree[j].wt<minWT2)
{
minE2=j;
minWT2=tree[j].wt;
}
}
//开始生成新的结点,并修改原父结点的下标
tree[ELEMENTCOUNT+i].parent=-1;
tree[ELEMENTCOUNT+i].wt=minWT1+minWT2;
//此处其左子树与右子树对应可以随意,因为其结点肯定要做为其它结点的子结点
tree[ELEMENTCOUNT+i].lchild=minE1;
tree[ELEMENTCOUNT+i].rchild=minE2;
//修改原根结点的父结点
tree[minE1].parent=tree[minE2].parent=ELEMENTCOUNT+i;
}
}
//采用栈的方式消除递归
void Display(hftree & tree)
{
int stack[100];
int top=0;
//根入栈
stack[top]=2*ELEMENTCOUNT-2;
while(top!=-1)
{
int index=stack[top];
top--;
while(index!=-1)
{
cout<<"结点的Data为:"<<tree[index].data<<","<<"结点的权值为:"<<tree[index].wt<<endl;
int left=-1,right=-1;
//寻找左节点和右节点
for(int i=0;i<2*ELEMENTCOUNT-1;i++)
{
if (tree[i].parent==index)
{
if (left==-1)
{
left=i;
}
else
{
right=i;
break;
}
}
}
if (left==-1 && right==-1)
{
index=-1;
}
else
{
index=left;
top++;
stack[top]=right;
}
}
}
}
int main(int argc, char* argv[])
{
hftree tree;
float WT[ELEMENTCOUNT];
tree[0].data='A';
WT[0]=0.1f;
tree[1].data='B';
WT[1]=0.2f;
tree[2].data='C';
WT[2]=0.3f;
tree[3].data='D';
WT[3]=0.2f;
tree[4].data='E';
WT[4]=0.2f;
huffman(ELEMENTCOUNT,WT,tree);
Display(tree);
return 0;
}
#include <iostream.h>
#include <malloc.h>
int const ELEMENTCOUNT=5; //判断条件的个数,即初始根节点的数量
struct node
{
float wt; //权值
int parent,lchild,rchild; //双亲的下标,左子树下标,右子树下标
char data; //该节点的值,这是我加的,方便我在显示的时候验证是否正确
};
typedef node hftree[2*ELEMENTCOUNT-1]; //保存所有Huffman树的节点的数组,需要2N-1个元素
//count:初始根结点的数量,WT[]保存各节点的权值,tree为huffman树
//算法中我没有使用书上的变量名,说实话,书上变量名乱起(i,j,k,x,y,m,n.),我看明白了算法后才知道各个变量的意义.
void huffman(int count,float WT[],hftree & tree)
{
float minWT1=0,minWT2=0; //保存第一小和第二小权值
int minE1=0,minE2=0; //保存第一小和第二小的根的在数组中的下标
int i=0,j=0;
//初始化树
for(i=0;i<2*ELEMENTCOUNT-1;i++)
{
tree[i].parent=-1;
tree[i].lchild=-1;
tree[i].rchild=-1;
if (i<count)
{
tree[i].wt=WT[i];
}
else
{
tree[i].wt=0;
tree[i].data='N'; //N为新生成的结点
}
}
//开始生成huffman树
for(i=0;i<ELEMENTCOUNT-1;i++) //因为总结点数为2*ELEMENTCOUNT-1,而生成的新结点数为总结点数-初始根结点数,即:2*ELEMENTCOUNT-1-ELEMENTCOUNT=ELEMENTCOUNT-1
{
minWT1=minWT2=1; //1为最大权值
minE1=minE2=0;
//循环找到第1小和第2小的节点,并记住其权值
for(j=0;j<ELEMENTCOUNT+i;j++) //j<ELEMENTCOUNT+i意味着,每次都从0循环至上次新增的节点,用以寻找剩下的根结点
{
if (tree[j].parent==-1 && tree[j].wt<minWT1)
{
minE2=minE1;
minE1=j;
minWT2=minWT1;
minWT1=tree[j].wt;
}
else if (tree[j].parent==-1 && tree[j].wt<minWT2)
{
minE2=j;
minWT2=tree[j].wt;
}
}
//开始生成新的结点,并修改原父结点的下标
tree[ELEMENTCOUNT+i].parent=-1;
tree[ELEMENTCOUNT+i].wt=minWT1+minWT2;
//此处其左子树与右子树对应可以随意,因为其结点肯定要做为其它结点的子结点
tree[ELEMENTCOUNT+i].lchild=minE1;
tree[ELEMENTCOUNT+i].rchild=minE2;
//修改原根结点的父结点
tree[minE1].parent=tree[minE2].parent=ELEMENTCOUNT+i;
}
}
//采用栈的方式消除递归
void Display(hftree & tree)
{
int stack[100];
int top=0;
//根入栈
stack[top]=2*ELEMENTCOUNT-2;
while(top!=-1)
{
int index=stack[top];
top--;
while(index!=-1)
{
cout<<"结点的Data为:"<<tree[index].data<<","<<"结点的权值为:"<<tree[index].wt<<endl;
int left=-1,right=-1;
//寻找左节点和右节点
for(int i=0;i<2*ELEMENTCOUNT-1;i++)
{
if (tree[i].parent==index)
{
if (left==-1)
{
left=i;
}
else
{
right=i;
break;
}
}
}
if (left==-1 && right==-1)
{
index=-1;
}
else
{
index=left;
top++;
stack[top]=right;
}
}
}
}
int main(int argc, char* argv[])
{
hftree tree;
float WT[ELEMENTCOUNT];
tree[0].data='A';
WT[0]=0.1f;
tree[1].data='B';
WT[1]=0.2f;
tree[2].data='C';
WT[2]=0.3f;
tree[3].data='D';
WT[3]=0.2f;
tree[4].data='E';
WT[4]=0.2f;
huffman(ELEMENTCOUNT,WT,tree);
Display(tree);
return 0;
}
一点说明:为什么在标题中要嵌入英文?原因是为了能够让国外的网友能查询到这篇文章。平常在Google上查资料的时候,经常参考国外网友的博客,帮助我解决了很多问题,所以我也想让他们能够参考我写的内容。当然文中我不可能全部译为英文,所以我尽量把代码粘全,靠代码说话吧。