哈夫曼树及哈夫曼编码的C程序实现(数据结构题)

问题描述〕输入一个有n个叶结点的权值构造一棵哈夫曼树;
(例如:n=8,权值为 5 29 7 8 14 23 3 11)
根据哈夫曼树构造哈夫曼编码,用指向字符串的指针数组来存放,从叶子到树根逆向求每个结点的哈夫曼编码

去年做的课程设计,有什么不合要求的自己改改

#include<string.h>
#include<stdlib.h>
#include<stdio.h>

int m,s1,s2;

typedef struct {
unsigned int weight;
unsigned int parent,lchild,rchild;
}HTNode,*HuffmanTree; //动态分配数组存储哈夫曼树
typedef char *HuffmanCode; //动态分配数组存储哈夫曼编码

void Select(HuffmanTree HT,int n) {
int i,j;
for(i = 1;i <= n;i++)
if(!HT[i].parent){s1 = i;break;}
for(j = i+1;j <= n;j++)
if(!HT[j].parent){s2 = j;break;}
for(i = 1;i <= n;i++)
if((HT[s1].weight>HT[i].weight)&&(!HT[i].parent)&&(s2!=i))s1=i;
for(j = 1;j <= n;j++)
if((HT[s2].weight>HT[j].weight)&&(!HT[j].parent)&&(s1!=j))s2=j;
}

void HuffmanCoding(HuffmanTree &HT, HuffmanCode HC[], int *w, int n) {
// 算法6.13
// w存放n个字符的权值(均>0),构造哈夫曼树HT,
// 并求出n个字符的哈夫曼编码HC
int i, j;
char *cd;
int p;
int cdlen;

if (n<=1) return;
m = 2 * n - 1;
HT = (HuffmanTree)malloc((m+1) * sizeof(HTNode)); // 0号单元未用
for (i=1; i<=n; i++) { //初始化
HT[i].weight=w[i-1];
HT[i].parent=0;
HT[i].lchild=0;
HT[i].rchild=0;
}
for (i=n+1; i<=m; i++) { //初始化
HT[i].weight=0;
HT[i].parent=0;
HT[i].lchild=0;
HT[i].rchild=0;
}
puts("\n哈夫曼树的构造过程如下所示:");
printf("HT初态:\n 结点 weight parent lchild rchild");
for (i=1; i<=m; i++)
printf("\n%4d%8d%8d%8d%8d",i,HT[i].weight,
HT[i].parent,HT[i].lchild, HT[i].rchild);
printf(" 按任意键,继续 ...");
getchar();
for (i=n+1; i<=m; i++) { // 建哈夫曼树
// 在HT[1..i-1]中选择parent为0且weight最小的两个结点,
// 其序号分别为s1和s2。
Select(HT, i-1);
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("\nselect: s1=%d s2=%d\n", s1, s2);
printf(" 结点 weight parent lchild rchild");
for (j=1; j<=i; j++)
printf("\n%4d%8d%8d%8d%8d",j,HT[j].weight,
HT[j].parent,HT[j].lchild, HT[j].rchild);
printf(" 按任意键,继续 ...");
getchar();
}

//------无栈非递归遍历哈夫曼树,求哈夫曼编码
cd = (char *)malloc(n*sizeof(char)); // 分配求编码的工作空间
p = m; cdlen = 0;
for (i=1; i<=m; ++i) // 遍历哈夫曼树时用作结点状态标志
HT[i].weight = 0;
while (p) {
if (HT[p].weight==0) { // 向左
HT[p].weight = 1;
if (HT[p].lchild != 0) { p = HT[p].lchild; cd[cdlen++] ='0'; }
else if (HT[p].rchild == 0) { // 登记叶子结点的字符的编码
HC[p] = (char *)malloc((cdlen+1) * sizeof(char));
cd[cdlen] ='\0'; strcpy(HC[p], cd); // 复制编码(串)
}
} else if (HT[p].weight==1) { // 向右
HT[p].weight = 2;
if (HT[p].rchild != 0) { p = HT[p].rchild; cd[cdlen++] ='1'; }
} else { // HT[p].weight==2,退回退到父结点,编码长度减1
HT[p].weight = 0; p = HT[p].parent; --cdlen;
}
}
} // HuffmanCoding
void main() {
HuffmanTree HT;HuffmanCode *HC;int *w,n,i;
puts("输入结点数:");
scanf("%d",&n);
HC = (HuffmanCode *)malloc(n*sizeof(HuffmanCode));
w = (int *)malloc(n*sizeof(int));
printf("输入%d个结点的权值\n",n);
for(i = 0;i < n;i++)
scanf("%d",&w[i]);
HuffmanCoding(HT,HC,w,n);
puts("\n各结点的哈夫曼编码:");
for(i = 1;i <= n;i++)
printf("%2d(%4d):%s\n",i,w[i-1],HC[i]);
getchar();
}
温馨提示:答案为网友推荐,仅供参考
第1个回答  推荐于2017-11-25
#include "string.h"
#include "stdio.h"
#define MAXVALUE 1000 /*定义最大权值*/
#define MAXLEAF 30 /*定义哈夫曼树叶结点个数*/
#define MAXNODE MAXLEAF*2-1
#define MAXBIT 30 /*定义哈夫曼编码的最大长度*/
typedef struct
{ int bit[MAXBIT];
int start;
} HCODETYPE;
typedef struct
{ int weight;
int parent;
int lchild;
int rchild;
} HNODETYPE;
char *getcode1(char *s1,char *s2,char *s3) /*首先去掉电文中的空格*/
{ char temp[128]="",*p,*q;
p=s1;
while ((q=strstr(p,s2))!=NULL)
{ *q='\0';
strcat(temp,p);
strcat(temp,s3);
p=q+strlen(s2); }
strcat(temp,p);
strcpy(s1,temp);
return s1;
}
/*再去掉重复出现的字符(即压缩电文),提取哈夫曼树叶结点*/
char * getcode (char *s1)
{ char s2[26],s5[26];
char temp[200]="",*p,*q,*r,*s3="";
int m,e,n=0;
m=strlen(s1);
while(m>0)
{ p=s1;
s2[0]=s1[0];
s2[1]='\0';
r=s2;
e=0;
while((q=strstr(p,r))!=NULL)
{ *q='\0';
strcat(temp,p);
strcat(temp,s3);
p=q+strlen(s2);
e++; }
m-=e;
strcat(temp,p);
strcpy(s1,temp);
s5[n]=s2[0];
n++;
strcpy(temp,"");
}
s5[n]='\0';
strcpy(s1,s5);
printf(" 压缩后的电文(即叶结点): %s\n",s1);
return s1;
}
HNODETYPE huffmantree(char *s2,char s3[])
{ HNODETYPE huffnode[MAXNODE];
HCODETYPE huffcode[MAXLEAF],cd;
int sum,i,j,n1,n2,x1,x2,p,k,c;
char s1[26]={'a','b','c','d','e','f','g','h','i','j','k','l','m',
'n','o','p','q','r','s','t','u','v','w','x','y','z'};
char s5[MAXLEAF];
int ww[26]={0},n=0;
strcpy( s5,s2);
sum=strlen(s2);
for(i=0;i<26;i++) /*统计所有字符出现的频度*/
for(j=0;j<sum;j++)
if(s2[j]==s1[i]) ww[i]++;
n=strlen(s3);
for (i=0;i<2*n-1;i++)
{ huffnode[i].weight=0;
huffnode[i].parent=-1;
huffnode[i].lchild=-1;
huffnode[i].rchild=-1; }
for(i=0;i<n;i++) /*分配给各叶结点权值*/
for(j=0;j<26;j++)
if (s3[i]==s1[j]) huffnode[i].weight=ww[j];
for (i=0;i<n-1;i++) /*构造哈夫曼树*/
{ n1=n2=MAXVALUE;
x1=x2=0;
for(j=0;j<n+i;j++)
{ if (huffnode[j].parent==-1 && huffnode[j].weight<n1)
{ n2=n1;
x2=x1;
n1=huffnode[j].weight;
x1=j; }
else
if (huffnode[j].parent==-1 && huffnode[j].weight<n2)
{ n2=huffnode[j].weight; x2=j;}
}
huffnode[x1].parent=n+i;
huffnode[x2].parent=n+i;
huffnode[n+i].weight=huffnode[x1].weight+huffnode[x2].weight;
huffnode[n+i].lchild=x1;
huffnode[n+i].rchild=x2;
}
for(i=0;i<n;i++) /*求每个叶结点的哈夫曼编码*/
{ cd.start=n-1;
c=i;
p=huffnode[c].parent;
while (p!=-1)
{ if (huffnode[p].lchild==c)
cd.bit[cd.start]=0;
else
cd.bit[cd.start]=1;
cd.start--;
c=p;
p=huffnode[c].parent;
}
for (j=cd.start+1;j<n;j++)
huffcode[i].bit[j]=cd.bit[j];
huffcode[i].start=cd.start;
}
printf(" 各叶结点对应哈夫曼编码 : ");/*输出每个叶结点的哈夫曼编码*/
for(i=0;i<n;i++)
{ for(j=huffcode[i].start+1;j<n;j++)
printf("%d",huffcode[i].bit[j]);
printf(" ");}
printf("\n 电文的全部哈夫曼编码 : ");/*输出电文的全部哈夫曼编码*/
for(k=0;k<sum;k++)
for(i=0;i<n;i++)
if(s2[k]==s3[i])
{ for(j=huffcode[i].start+1;j<n;j++)
printf("%d",huffcode[i].bit[j]);
printf(" "); }
printf("\n");
}
main()
{
char s1[MAXLEAF],s2[MAXLEAF];
printf("\n 请输入电文 : ");
gets(s1);
strcpy(s2,getcode1(s1," ",""));
huffmantree(s1,getcode(s2));
}本回答被网友采纳
第2个回答  2013-12-04
#include<stdio.h>
#include<stdlib.h>
#define MAXINF 10000

struct htnode
{
int ww;
int parent,llink,rlink;
};

struct httree
{
int m;
int root;
struct htnode *ht;
};
typedef struct httree *phttree;

phttree huffman(int m,int *w)
{
phttree pht;
int i,j,x1,x2,m1,m2;
pht=(phttree)malloc(sizeof(struct httree));
pht->ht=(struct htnode*)malloc(sizeof(struct htnode)*(2*m-1));
for(i=0;i<2*m-1;i++)
{
pht->ht[i].llink=-1;
pht->ht[i].rlink=-1;
pht->ht[i].parent=-1;
if(i<m)
pht->ht[i].ww=w[i];
else
pht->ht[i].ww=-1;
}
for(i=0;i<m-1;i++)
{
m1=MAXINF;m2=MAXINF;
x1=-1;x2=-1;
for(j=0;j<m+i;j++)
if(pht->ht[j].ww<m1&&pht->ht[j].parent==-1)
{
m2=m1;x2=x1;m1=pht->ht[j].ww;x1=j;
}
else if(pht->ht[j].ww<m2&&pht->ht[j].parent==-1)
{
m2=pht->ht[j].ww;x2=j;
}
pht->ht[x1].parent=m+i;pht->ht[x2].parent=m+i;
pht->ht[m+i].ww=m1+m2;pht->ht[m+i].llink=x1;
pht->ht[m+i].rlink=x2;
}
pht->root=2*m-2;
return pht;
}

int main()
{
int i,m,*a;
phttree kun;
printf("输入权值个数:");
scanf("%d",&m);
printf("输入权值:\n");
for(i=0;i<m;i++)
scanf("%d",&a[i]);
kun=huffman(m,a);
for(i=0;i<2*m-1;i++)
{
printf("%d%5d%5d",i,kun->ht[i].ww,kun->ht[i].parent);
printf("%5d%5d\n",kun->ht[i].llink,kun->ht[i].rlink);
}
system("pause");
return 0;
}
今年才开课,前不久写的,呵呵本回答被网友采纳
相似回答