❶ [數據結構課程設計代碼]C編寫,好的話追加80分,謝謝]
typedef struct
{
unsigned int weight;
unsigned int parent,lchild,rchild;
}HTNode,*HuffmanTree; /* 動態分配數組存儲赫夫曼樹 */
typedef char **HuffmanCode; /* 動態分配數組存儲赫夫曼編碼表 */
/* 求赫夫曼編碼 */
#include"c1.h"
#include"c6-7.h"
#include"func6-1.c"
void HuffmanCoding(HuffmanTree *HT,HuffmanCode *HC,int *w,int n) /* 演算法6.12 */
{ /* w存放n個字元的權值(均>0),構造赫夫曼樹HT,並求出n個字元的赫夫曼編碼HC */
int m,i,s1,s2,start;
unsigned c,f;
HuffmanTree p;
char *cd;
if(n<=1)
return;
m=2*n-1;
*HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); /* 0號單元未用 */
for(p=*HT+1,i=1;i<=n;++i,++p,++w)
{
(*p).weight=*w;
(*p).parent=0;
(*p).lchild=0;
(*p).rchild=0;
}
for(;i<=m;++i,++p)
(*p).parent=0;
for(i=n+1;i<=m;++i) /* 建赫夫曼樹 */
{ /* 在HT[1~i-1]中選擇parent為0且weight最小的兩個結點,其序號分別為s1和s2 */
select(*HT,i-1,&s1,&s2);
(*HT)[s1].parent=(*HT)[s2].parent=i;
(*HT)[i].lchild=s1;
(*HT)[i].rchild=s2;
(*HT)[i].weight=(*HT)[s1].weight+(*HT)[s2].weight;
}
/* 從葉子到根逆向求每個字元的赫夫曼編碼 */
*HC=(HuffmanCode)malloc((n+1)*sizeof(char*));
/* 分配n個字元編碼的頭指針向量([0]不用) */
cd=(char*)malloc(n*sizeof(char)); /* 分配求編碼的工作空間 */
cd[n-1]='\0'; /* 編碼結束符 */
for(i=1;i<=n;i++)
{ /* 逐個字元求赫夫曼編碼 */
start=n-1; /* 編碼結束符位置 */
for(c=i,f=(*HT)[i].parent;f!=0;c=f,f=(*HT)[f].parent)
/* 從葉子到根逆向求編碼 */
if((*HT)[f].lchild==c)
cd[--start]='0';
else
cd[--start]='1';
(*HC)[i]=(char*)malloc((n-start)*sizeof(char));
/* 為第i個字元編碼分配空間 */
strcpy((*HC)[i],&cd[start]); /* 從cd復制編碼(串)到HC */
}
free(cd); /* 釋放工作空間 */
}
void main()
{
HuffmanTree HT;
HuffmanCode HC;
int *w,n,i;
printf("請輸入權值的個數(>1): ");
scanf("%d",&n);
w=(int*)malloc(n*sizeof(int));
printf("請依次輸入%d個權值(整型):\n",n);
for(i=0;i<=n-1;i++)
scanf("%d",w+i);
HuffmanCoding(&HT,&HC,w,n);
for(i=1;i<=n;i++)
puts(HC[i]);
}
/*無棧非遞歸遍歷赫夫曼樹,求赫夫曼編碼*/
#include"c1.h"
#include"c6-7.h"
#include"func6-1.c"
void HuffmanCoding(HuffmanTree *HT,HuffmanCode *HC,int *w,int n) */
{ /* w存放n個字元的權值(均>0),構造赫夫曼樹HT,並求出n個字元的赫夫曼編碼HC */
int m,i,s1,s2; /* 此句與algo6-1.c不同 */
unsigned c,cdlen; /* 此句與algo6-1.c不同 */
HuffmanTree p;
char *cd;
if(n<=1)
return;
m=2*n-1;
*HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); /* 0號單元未用 */
for(p=*HT+1,i=1;i<=n;++i,++p,++w)
{
(*p).weight=*w;
(*p).parent=0;
(*p).lchild=0;
(*p).rchild=0;
}
for(;i<=m;++i,++p)
(*p).parent=0;
for(i=n+1;i<=m;++i) /* 建赫夫曼樹 */
{ /* 在HT[1~i-1]中選擇parent為0且weight最小的兩個結點,其序號分別為s1和s2 */
select(*HT,i-1,&s1,&s2);
(*HT)[s1].parent=(*HT)[s2].parent=i;
(*HT)[i].lchild=s1;
(*HT)[i].rchild=s2;
(*HT)[i].weight=(*HT)[s1].weight+(*HT)[s2].weight;
}
/* 以下為演算法6.13,無棧非遞歸遍歷赫夫曼樹,求赫夫曼編碼,以上同演算法6.12 */
*HC=(HuffmanCode)malloc((n+1)*sizeof(char*));
/* 分配n個字元編碼的頭指針向量([0]不用) */
cd=(char*)malloc(n*sizeof(char)); /* 分配求編碼的工作空間 */
c=m;
cdlen=0;
for(i=1;i<=m;++i)
(*HT)[i].weight=0; /* 遍歷赫夫曼樹時用作結點狀態標志 */
while(c)
{
if((*HT)[c].weight==0)
{ /* 向左 */
(*HT)[c].weight=1;
if((*HT)[c].lchild!=0)
{
c=(*HT)[c].lchild;
cd[cdlen++]='0';
}
else if((*HT)[c].rchild==0)
{ /* 登記葉子結點的字元的編碼 */
(*HC)[c]=(char *)malloc((cdlen+1)*sizeof(char));
cd[cdlen]='\0';
strcpy((*HC)[c],cd); /* 復制編碼(串) */
}
}
else if((*HT)[c].weight==1)
{ /* 向右 */
(*HT)[c].weight=2;
if((*HT)[c].rchild!=0)
{
c=(*HT)[c].rchild;
cd[cdlen++]='1';
}
}
else
{ /* HT[c].weight==2,退回 */
(*HT)[c].weight=0;
c=(*HT)[c].parent;
--cdlen; /* 退到父結點,編碼長度減1 */
}
}
free(cd);
}
void main()
{ /* 主程序同algo6-1.c */
HuffmanTree HT;
HuffmanCode HC;
int *w,n,i;
printf("請輸入權值的個數(>1): ");
scanf("%d",&n);
w=(int *)malloc(n*sizeof(int));
printf("請依次輸入%d個權值(整型):\n",n);
for(i=0;i<=n-1;i++)
scanf("%d",w+i);
HuffmanCoding(&HT,&HC,w,n);
for(i=1;i<=n;i++)
puts(HC[i]);
}