贪心法-C语言-霍夫曼编码
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
cd[n-1]='\0'; //从右向左逐位存放编码,首先存放编码结束符
for(i=1; i<=n; i++) //求n个叶子结点对应的哈夫曼编码
{
a[i]=0;
start=n-1; //起始指针位置在最右边
for(c=i,p=(*ht)[i].parent; p!=0; c=p,p=(*ht)[p].parent) //从叶子到根结点求编码
贪心算法
霍夫曼编码
学院计算机科学与软件
姓名XXX
班级XXXXXX
学号XXXX
课程名称计算机算法设计与分析
教师韩其睿
日期:2015年4月22日
【实验题目】
设需要编码的字符集为{ d1,d2,…,dn}它们出现的频率为{ p1,p2,…,pn},应用霍夫曼树构造最短的非等长编码。
【实验要求】
证明霍夫曼编码问题具有最优子结构性质和贪心选择性质,设计贪心算法求解霍夫曼编码问题,编写实验程序,给出测试数据和测试结果。
{
int m,i,s1,s2;
m=2*n-1;
*ht=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
for(i=1; i<=n; i++)
{
(*ht)[i].weight=w[i];
(*ht)[i].LChild=0;
(*ht)[i].parent=0;
(*ht)[i].RChild=0;
(*ht)[s1].parent=i;
(*ht)[s2].parent=i;
(*ht)[i].LChild=s1;
(*ht)[i].RChild=s2;
(*ht)[i].weight=(*ht)[s1].weight+(*ht)[s2].weight;
}
printf("\n");
}
void CrtHuffmanCode(HuffmanTree *ht, HuffmanCode *hc, int n)
}
void main()
{
HuffmanTree HT;
HuffmanCode HC;
int *w,i,n,wei;
printf("请输入结点个数:" );
scanf("%d",&n);
w=(int *)malloc((n+1)*sizeof(int));
printf("\n输入这%d个元素的权值:\n",n);
for(i=1; i<=n; i++)
{
printf("%d: ",i);
fflush(stdin);
scanf("%d",&wei);
w[i]=wei;
}
CrtHuffmanTree(&HT,w,n);
CrtHuffmanCode(&HT,&HC,n);
}
【运行测试】
【实验感悟】
1.理解了贪心算法的概念和一般理论。
{
if( (*ht)[p].LChild==c)
{
cd[--start]='1'; //左分支标1
a[i]++;
}
else
{
cd[--start]='0'; //右分支标0
a[i]++;
}
}
hc[i]=(char *)malloc((n-start)*sizeof(char)); //为第i个编码分配空间
霍夫曼树共有2n-1个结点,设置一个数组ht[2n-1]保存霍夫曼树中各结点的信息。数组元素结构为
weight
lc来自百度文库ild
rchild
parent
weight:结点的权值
lchild:结点的左孩子结点在数组中的下标.
rchild:结点的右孩子结点在数组中的下标
parent:结点的双亲结点在数组中的下标
{
min=i;
break;
}
}
for(i=1; i<=n; i++)
{
if((*ht)[i].parent==0 && i!=(*s1))
{
if((*ht)[i].weight<(*ht)[min].weight)
min=i;
}
}
*s2=min;
}
void CrtHuffmanTree(HuffmanTree *ht,int *w,int n)
{
char *cd;
int a[100];
int i,start,p,w=0;
unsigned int c;
hc=(HuffmanCode *)malloc((n+1)*sizeof(char *)); //分配n个编码的头指针
cd=(char *)malloc(n*sizeof(char)); //分配求当前编码的工作空间
{
min=i;
break;
}
}
for(i=1; i<=n; i++)
{
if((*ht)[i].parent==0)
{
if((*ht)[i].weight<(*ht)[min].weight)
min=i;
}
}
*s1=min;
for(i=1; i<=n; i++)
{
if((*ht)[i].parent==0 && i!=(*s1))
strcpy(hc[i],&cd[start]); //将cd复制编码到hc
}
free(cd);
for(i=1; i<=n; i++)
printf("权值为%d的哈夫曼编码为:%s\n",(*ht)[i].weight,hc[i]);
for(i=1; i<=n; i++)
w+=(*ht)[i].weight*a[i];
【算法源码】
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
unsigned int weight; //存放权值
unsigned int parent,LChild,RChild;
} HTNode, *HuffmanTree;
}
for(i=n+1; i<=m; i++)
{
(*ht)[i].weight=0;
(*ht)[i].LChild=0;
(*ht)[i].parent=0;
(*ht)[i].RChild=0;
}
for(i=n+1; i<=m; i++) //创建非叶子结点,建哈夫曼树
{
Select(ht,i-1,&s1,&s2);
typedef char *HuffmanCode;
//选择两个双亲为0,且权重最小的结点s1和s2
void Select(HuffmanTree *ht,int n,int *s1,int *s2)
{
int i,min;
for(i=1; i<=n; i++)
{
if((*ht)[i].parent==0)
【实验目的】
1)掌握贪心选择性质的证明方法。
2)掌握贪心法的设计思想并能熟练运用。
【实验思路】
设需要编码的字符集为{ d1,d2,…,dn}它们出现的频率为{ p1,p2,…,pn},以d1,d2,…,dn作为叶子结点,p1,p2,…,pn作为叶子结点的权值,构造一棵霍夫曼树,规定霍夫曼树的左子树代表0,右子树代表1,由根结点到叶子结点经过的路径组成的0和1的序列是该叶子结点对应字符的编码,即霍夫曼编码。
2.初步掌握了贪心算法的设计思路。
for(i=1; i<=n; i++) //求n个叶子结点对应的哈夫曼编码
{
a[i]=0;
start=n-1; //起始指针位置在最右边
for(c=i,p=(*ht)[i].parent; p!=0; c=p,p=(*ht)[p].parent) //从叶子到根结点求编码
贪心算法
霍夫曼编码
学院计算机科学与软件
姓名XXX
班级XXXXXX
学号XXXX
课程名称计算机算法设计与分析
教师韩其睿
日期:2015年4月22日
【实验题目】
设需要编码的字符集为{ d1,d2,…,dn}它们出现的频率为{ p1,p2,…,pn},应用霍夫曼树构造最短的非等长编码。
【实验要求】
证明霍夫曼编码问题具有最优子结构性质和贪心选择性质,设计贪心算法求解霍夫曼编码问题,编写实验程序,给出测试数据和测试结果。
{
int m,i,s1,s2;
m=2*n-1;
*ht=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
for(i=1; i<=n; i++)
{
(*ht)[i].weight=w[i];
(*ht)[i].LChild=0;
(*ht)[i].parent=0;
(*ht)[i].RChild=0;
(*ht)[s1].parent=i;
(*ht)[s2].parent=i;
(*ht)[i].LChild=s1;
(*ht)[i].RChild=s2;
(*ht)[i].weight=(*ht)[s1].weight+(*ht)[s2].weight;
}
printf("\n");
}
void CrtHuffmanCode(HuffmanTree *ht, HuffmanCode *hc, int n)
}
void main()
{
HuffmanTree HT;
HuffmanCode HC;
int *w,i,n,wei;
printf("请输入结点个数:" );
scanf("%d",&n);
w=(int *)malloc((n+1)*sizeof(int));
printf("\n输入这%d个元素的权值:\n",n);
for(i=1; i<=n; i++)
{
printf("%d: ",i);
fflush(stdin);
scanf("%d",&wei);
w[i]=wei;
}
CrtHuffmanTree(&HT,w,n);
CrtHuffmanCode(&HT,&HC,n);
}
【运行测试】
【实验感悟】
1.理解了贪心算法的概念和一般理论。
{
if( (*ht)[p].LChild==c)
{
cd[--start]='1'; //左分支标1
a[i]++;
}
else
{
cd[--start]='0'; //右分支标0
a[i]++;
}
}
hc[i]=(char *)malloc((n-start)*sizeof(char)); //为第i个编码分配空间
霍夫曼树共有2n-1个结点,设置一个数组ht[2n-1]保存霍夫曼树中各结点的信息。数组元素结构为
weight
lc来自百度文库ild
rchild
parent
weight:结点的权值
lchild:结点的左孩子结点在数组中的下标.
rchild:结点的右孩子结点在数组中的下标
parent:结点的双亲结点在数组中的下标
{
min=i;
break;
}
}
for(i=1; i<=n; i++)
{
if((*ht)[i].parent==0 && i!=(*s1))
{
if((*ht)[i].weight<(*ht)[min].weight)
min=i;
}
}
*s2=min;
}
void CrtHuffmanTree(HuffmanTree *ht,int *w,int n)
{
char *cd;
int a[100];
int i,start,p,w=0;
unsigned int c;
hc=(HuffmanCode *)malloc((n+1)*sizeof(char *)); //分配n个编码的头指针
cd=(char *)malloc(n*sizeof(char)); //分配求当前编码的工作空间
{
min=i;
break;
}
}
for(i=1; i<=n; i++)
{
if((*ht)[i].parent==0)
{
if((*ht)[i].weight<(*ht)[min].weight)
min=i;
}
}
*s1=min;
for(i=1; i<=n; i++)
{
if((*ht)[i].parent==0 && i!=(*s1))
strcpy(hc[i],&cd[start]); //将cd复制编码到hc
}
free(cd);
for(i=1; i<=n; i++)
printf("权值为%d的哈夫曼编码为:%s\n",(*ht)[i].weight,hc[i]);
for(i=1; i<=n; i++)
w+=(*ht)[i].weight*a[i];
【算法源码】
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
unsigned int weight; //存放权值
unsigned int parent,LChild,RChild;
} HTNode, *HuffmanTree;
}
for(i=n+1; i<=m; i++)
{
(*ht)[i].weight=0;
(*ht)[i].LChild=0;
(*ht)[i].parent=0;
(*ht)[i].RChild=0;
}
for(i=n+1; i<=m; i++) //创建非叶子结点,建哈夫曼树
{
Select(ht,i-1,&s1,&s2);
typedef char *HuffmanCode;
//选择两个双亲为0,且权重最小的结点s1和s2
void Select(HuffmanTree *ht,int n,int *s1,int *s2)
{
int i,min;
for(i=1; i<=n; i++)
{
if((*ht)[i].parent==0)
【实验目的】
1)掌握贪心选择性质的证明方法。
2)掌握贪心法的设计思想并能熟练运用。
【实验思路】
设需要编码的字符集为{ d1,d2,…,dn}它们出现的频率为{ p1,p2,…,pn},以d1,d2,…,dn作为叶子结点,p1,p2,…,pn作为叶子结点的权值,构造一棵霍夫曼树,规定霍夫曼树的左子树代表0,右子树代表1,由根结点到叶子结点经过的路径组成的0和1的序列是该叶子结点对应字符的编码,即霍夫曼编码。
2.初步掌握了贪心算法的设计思路。