哈夫曼编码译码 C语言,【求助】严蔚敏版数据结构 哈夫曼编码译码
該樓層疑似違規(guī)已被系統(tǒng)折疊?隱藏此樓查看此樓
#include
#include
#include
typedef char* HuffmanCode;/*動(dòng)態(tài)分配數(shù)組,存儲(chǔ)哈夫曼編碼*/
typedef struct
{
unsigned int weight ; /* 用來(lái)存放各個(gè)結(jié)點(diǎn)的權(quán)值*/
unsigned int parent, LChild,RChild ; /*指向雙親、孩子結(jié)點(diǎn)的指針*/
}HTNode, * HuffmanTree; /*動(dòng)態(tài)分配數(shù)組,存儲(chǔ)哈夫曼樹*/
void select(HuffmanTree *ht,int n, int *s1, int *s2) /*選擇霍夫曼樹中權(quán)值最小的兩個(gè)結(jié)點(diǎn)
并返回他們的序號(hào)*/
{
int i;
int min;
for(i=1; i<=n; i++)
{
if((*ht)[i].parent == 0) //雙親結(jié)點(diǎn)為0
{
min = i; // 將第一個(gè)雙親結(jié)點(diǎn)為0的葉結(jié)點(diǎn)序號(hào)給min
i = n+1; //將i改為非葉結(jié)點(diǎn)
}
}
for(i=1; i<=n; i++)
{
if((*ht)[i].parent == 0)
{ //比較各葉節(jié)點(diǎn)權(quán)值與剛才min號(hào)結(jié)點(diǎn)比較
if((*ht)[i].weight < (*ht)[min].weight)
min = i; //MIN放權(quán)值最小的兩個(gè)結(jié)點(diǎn)序號(hào)小的那個(gè)
}
}
*s1 = min; //s1存放這個(gè)小的序號(hào)
for(i=1; i<=n; i++)
{
if((*ht)[i].parent == 0 && i!=(*s1)) //再搜索除s1以外的葉結(jié)點(diǎn)
{
min = i; //重復(fù)上面取最小葉結(jié)點(diǎn)的過(guò)程
i = n+1;
}
}
for(i=1; i<=n; i++)
{
if((*ht)[i].parent == 0 && i!=(*s1))
{
if((*ht)[i].weight < (*ht)[min].weight)
min = i; //這個(gè)min存放權(quán)值第二小的結(jié)點(diǎn)序號(hào)再給s2
}
}
*s2 = min;
} //最后將最小的兩個(gè)結(jié)點(diǎn)的序號(hào)返回
void CrtHuffmanTree(HuffmanTree *ht , int *w, int n)
{ /* w存放已知的n個(gè)權(quán)值,構(gòu)造哈夫曼樹ht */
int m,i; //m是結(jié)點(diǎn)總數(shù)
int s1,s2;
m=2*n-1;
*ht=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); /*0號(hào)單元未使用*/
for(i=1;i<=n;i++)
{/*1-n號(hào)放葉子結(jié)點(diǎn),初始化*/
(*ht)[i].weight = w[i];
(*ht)[i].LChild = 0;
(*ht)[i].parent = 0;
(*ht)[i].RChild = 0;
}
for(i=n+1;i<=m;i++)
{
(*ht)[i].weight = 0;
(*ht)[i].LChild = 0;
(*ht)[i].parent = 0;
(*ht)[i].RChild = 0;
} /*非葉子結(jié)點(diǎn)初始化*/
/* ------------初始化完畢!對(duì)應(yīng)算法步驟1---------*/
for(i=n+1;i<=m;i++) /*創(chuàng)建非葉子結(jié)點(diǎn),建哈夫曼樹*/
{ /*在(*ht)[1]~(*ht)[i-1]的范圍內(nèi)就是選擇葉子結(jié)點(diǎn)
建成一步后,增加了一個(gè)雙親節(jié)點(diǎn),則此時(shí)需要增加一個(gè)結(jié)點(diǎn)搜索最小值
由于先前的葉子結(jié)點(diǎn)的雙親結(jié)點(diǎn)不是0,則不影響搜索
選擇兩個(gè)parent為0且weight最小的結(jié)點(diǎn),其序號(hào)分別賦值給s1、s2返回*/
select(ht,i-1,&s1,&s2);
(*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;
}
}/*哈夫曼樹建立完畢*/
void outputHuffman(HuffmanTree HT, int m) //遞歸輸出霍夫曼樹
{
if(m!=0)
{
printf("%d ", HT[m].weight);
outputHuffman(HT,HT[m].LChild);
outputHuffman(HT,HT[m].RChild);
}
}
void CrtHuffmanCode(HuffmanTree *ht, HuffmanCode *hc, int n)
/*從葉子結(jié)點(diǎn)到根,逆向求每個(gè)葉子結(jié)點(diǎn)對(duì)應(yīng)的哈夫曼編碼*/
{
char *cd; //cd是用來(lái)存放需要編碼的0,1.
int i;
unsigned int c;
int start;
int p; //指向第i個(gè)葉子結(jié)點(diǎn)的雙親結(jié)點(diǎn)
hc=(HuffmanCode *)malloc((n+1)*sizeof(char *)); /*分配n個(gè)編碼的頭指針*hc即使hc[n]
n個(gè)編碼的頭指針0號(hào)未使用*/
cd=(char * )malloc(n * sizeof(char )); /*分配求當(dāng)前編碼的工作空間即是
將那些個(gè)0,1存到數(shù)組中 0,1以字符形式輸出*/
cd[n-1]='\0'; /*從右向左逐位存放編碼,首先存放編碼結(jié)束符*/
for(i=1;i<=n;i++) /*求n個(gè)葉子結(jié)點(diǎn)對(duì)應(yīng)的哈夫曼編碼*/
{
start=n-1; /*初始化編碼起始指針*/
for(c=i,p=(*ht)[i].parent; p!=0; c=p,p=(*ht)[p].parent) /*從葉子到根結(jié)點(diǎn)求編碼*/
if( (*ht)[p].LChild == c)
cd[--start]='0'; /*左分支標(biāo)0*/
else
cd[--start]='1'; /*右分支標(biāo)1*/
hc[i]=(char *)malloc((n-start)*sizeof(char)); /*為第i個(gè)編碼分配空間*/
strcpy(hc[i],&cd[start]); /*將當(dāng)前到末尾的霍夫曼編碼賦給hc數(shù)組*/
}
free(cd);
for(i=1;i<=n;i++)
printf("%d編碼為%s\n",(*ht)[i].weight,hc[i]);
}
void main()
{
HuffmanTree HT;
HuffmanCode HC; //定義編碼指針 即編碼數(shù)組,存放所有葉子結(jié)點(diǎn)的0,1編碼
int *p;
int i,n; // the number of elements;
int val; // the weight of a element;
int m;
printf("input the total number of the Huffman Tree:" );
scanf("%d",&n); //有n個(gè)已知權(quán)值的結(jié)點(diǎn)
p=(int *)malloc((n+1)*sizeof(int)); //分配給權(quán)值空間
for(i=1;i<=n;i++)
{
printf("input the %d element's weight:",i);
scanf("%d",&val);
p[i]=val;
}
CrtHuffmanTree(&HT,p,n);
m = 2*n-1;
outputHuffman(HT,m); //輸出所有的霍夫曼結(jié)點(diǎn)的權(quán)值
printf("\n");
CrtHuffmanCode(&HT,&HC,n); //創(chuàng)建霍夫曼編碼,hc是編碼數(shù)組
}
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的哈夫曼编码译码 C语言,【求助】严蔚敏版数据结构 哈夫曼编码译码的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: linux 以太网转wifi,LINUX
- 下一篇: c语言程序设计第二章的答案,C语言程序设