哈夫曼編碼c語言實現
㈠ 哈夫曼樹及哈夫曼編碼,c語言演算法實現
#include<stdio.h>
#define MAX 30
#define inf 100000000
typedef char valType;
typedef int wghType;
struct HFMnode
{
valType data;
wghType weight;
int parent;
int lchild;
int rchild;
};
struct HFMcode
{
char code[MAX];
int start;
};
void createHFMtree(HFMnode *node,int n)
{
int i,m1,m2,l,r;
for(i=n+1;i<=2*n-1;i++)
{
m1=m2=inf;
l=r=0;
int k;
for(k=1;k<=i-1;k++)
if(node[k].parent==0)
{
if(node[k].weight<m1)
{
m2=m1;
r=l;
m1=node[k].weight;
l=k;
}
else if(node[k].weight<m2)
{
m2=node[k].weight;
r=k;
}
}
node[i].weight=node[l].weight+node[r].weight;
node[i].lchild=l;
node[i].rchild=r;
node[l].parent=i;
node[r].parent=i;
}
}
void createHFMcode(HFMnode *node, HFMcode *hcode,int n)
{
int i;
for(i=1;i<=n;i++)
{
HFMcode d;
d.start=n;
int num=i;
int father=node[num].parent;
while(father!=0)
{
if(node[father].lchild==num)
d.code[d.start--]='0';
else d.code[d.start--]='1';
num=father;
father=node[num].parent;
}
hcode[i]=d;
}
}
void printHFMcode(HFMnode * node,HFMcode * hcode,int n)
{
int i;
for(i=1;i<=n;i++)
{
printf("%c: ",node[i].data);
for(int k=hcode[i].start+1;k<=n;k++)
putchar(hcode[i].code[k]);
puts("");
}
}
void main()
{
HFMnode node[2*MAX];HFMcode hcd[MAX];
int n;
scanf("%d\n",&n);
for(int i=1;i<=n;i++){
printf("輸入第%d個節點的值\n",i);
scanf("%c",&node[i].data);
printf("輸入它的權重\n");
scanf("%d\n",&node[i].weight);
}
for(int i=1;i<=2*n-1;i++)
node[i].parent=node[i].lchild=node[i].rchild=0;
createHFMtree(node,n);
createHFMcode(node,hcd,n);
printHFMcode(node,hcd,n);
}
參考資料:http://blog.csdn.net/heyongluoyao8/article/details/6925209
輸入文件格式例:
26
A 7
B 2
C 2
D 3
E 11
F 2
G 2
H 6
I 6
J 1
K 1
L 4
M 3
N 7
O 9
P 2
Q 1
R 6
S 6
T 8
U 4
V 1
W 2
X 1
Y 2
Z 1
㈡ 哈夫曼樹及哈夫曼編碼的C程序實現(數據結構題)
去年做的課程設計,有什麼不合要求的自己改改
#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();
}
㈢ 霍夫曼編碼 用c語言實現
以前寫的,證明最優子結構,隨便一本演算法書上就有. #include<stdio.h>
#include<stdlib.h>
#define NIL -2
#define Size_Max_bm 30
#define left(i) (2*(i)+1)
#define right(i) (2*(i)+2)
#define swap(a,b) {cjys t;t=(a);(a)=(b);(b)=t;}
#define parent(i) ((i)%2?((i)-1)/2:((i)-2)/2)typedef struct cjys
{
char sj;
int pl;
struct cjys *left;
struct cjys *right;
}cjys;typedef struct cjdl
{
int size;
int leapsize;
cjys *p;
}cjdl;
cjys *fpnn(void);
void input(cjdl *p);
cjys *fpnn(void);
void zxdwh(cjys *p, int i, int leapsize);
void rd(cjdl *p, cjys tp);
cjys cd(cjdl *p);
void hbs(cjdl *p);
cjys *cjs(cjdl *p);
void bls(cjys *p,int *jl, int i);
void disp(char *tp, cjys *p);int main()
{
cjdl p;
char x[255];
cjys *re=NULL;
int jl[Size_Max_bm];
input(&p);
re=cjs(&p);
printf("對照編碼圖為:\n");
bls(re,jl,0);
freopen("CON","r",stdin);
printf("輸入Huffman碼(VLC):");
scanf("%s",x);
disp(x,re);
system("pause");
}
void input(cjdl *p)
{
int i;
cjys *tp;
tp=fpnn();
printf("輸入字母個數:");
scanf("%d", &p->size);
p->p=malloc(sizeof(cjys)*p->size);
p->leapsize=0;
for(i = 0; i < p->size;i++)
{
printf("輸入第%d字母:",i+1),scanf(" %c",&tp->sj);
printf("輸入出現次數(頻率整數):"),scanf("%d",&tp->pl);
rd(p,*tp);
}
free(tp);
}
cjys *fpnn(void)
{
cjys *p=NULL;
p=malloc(sizeof(cjys));
p->left=NULL;
p->right=NULL;
return p;
} void zxdwh(cjys *p, int i, int leapsize)
{
int l=left(i), r=right(i), mini=i;
if(l<leapsize && p[l].pl<p[mini].pl)
mini=l;
if(r<leapsize && p[r].pl<p[mini].pl)
mini=r;
if(mini != i)
{
swap(p[i],p[mini]);
zxdwh(p,mini,leapsize);
}
}
void rd(cjdl *p, cjys tp)
{
if(p->leapsize == p->size)
{
printf("隊列已滿!");
exit(0);
}
p->p[p->leapsize]=tp;
int j=p->leapsize,k=parent(j);
while(k>=0 && p->p[j].pl < p->p[k].pl)
{
swap(p->p[j],p->p[k]);
j=k;
k=parent(j);
}
p->leapsize++;
}
cjys cd(cjdl *p)
{
if(p->leapsize == 0)
{
printf("隊列已空!");
exit(0);
}
cjys tp=p->p[0];
p->leapsize--;
p->p[0]=p->p[p->leapsize];
zxdwh(p->p,0,p->leapsize);
return tp;
}
void hbs(cjdl *p)
{
cjys *p1=NULL, *p2=NULL;
cjys tp;
p1=fpnn();
p2=fpnn();
*p1=cd(p);
*p2=cd(p);
tp.left=p1;
tp.right=p2;
tp.pl=p1->pl+p2->pl;
tp.sj=NIL;
rd(p,tp);
}cjys *cjs(cjdl *p)
{
int i, n=p->leapsize;
cjys *tp=NULL;
tp=fpnn();
for(i = 0; i < n-1; i++)
hbs(p);
*tp=p->p[0];
return tp;
}
void bls(cjys *p, int *jl, int i)
{
if(p == NULL)
return;
if(p->sj!=NIL)
{
int i2;
printf("%c:",p->sj);
for(i2 = 0; i2 < i; i2++)
printf("%d",jl[i2]);
printf("\n");
}
jl[i]=0;
bls(p->left,jl,i+1);
jl[i]=1;
bls(p->right,jl,i+1);
}
void disp(char *tp, cjys *p)
{
cjys *ttp=NULL;
int pd=0;
while(1)
{
ttp=p;
while(1)
{
if(ttp->sj != NIL)
{
printf("%c",ttp->sj);
break;
}
if(*tp == '\0')
{
pd=1;
break;
}
if(*tp++ == '0' )
ttp=ttp->left;
else
ttp=ttp->right;
}
if(pd)
break;
}
}
㈣ Huffman編碼C語言實現
說明:本程序是依據嚴蔚敏的數據結構(C語言版)上的代碼實現的。
#pragmaonce
#include<stdio.h>
#include<tchar.h>
#include<stdlib.h>
#define MAX 100
typedefstruct{ //節點
int weight;
int parent, lchild, rchild;
}HTNode, *HuffmanTree;
typedefchar **HuffmanCode; //字元串數組,用於存儲葉子節點的編碼
void SelectMinNode(HuffmanTree &HT, int m, int &i1, int &i2) //找出權值最小的兩個節點對應的數組下標
{
HuffmanTree p = HT;
int s1, s2;
s1 = s2 = MAX;
i1 = i2 = 1;
for(int i=1; i<=m; i++)
{
if(!(p+i)->parent)
{
if((p+i)->weight < s1)
{
i2 = i;
s1 = (p+i)->weight ;
}
}
}
for(int i=1; i<=m; i++)
{
if(!(p+i)->parent && i!=i2)
{
if((p+i)->weight < s2)
{
i1 = i;
s2 = (p+i)->weight ;
}
}
}
}
void StrCopy(char *p, char *q, int start) //從字元數組中第start個字元開始復制
{
char *c1, *c2;
c1 = p;
while(q[start] != '\0')
{
*c1 = q[start];
c1++;
start++;
}
*c1 = q[start];//別忘了將『\n』復制過來
}
void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n)
{ //HT赫夫曼樹節點數組,HC存儲赫夫曼編碼,*w 節點權值數組的首地址,n節點個數
int i, i1, i2, m;
HuffmanTree p;
if(n<=1) return;
m = 2 * n -1; //n個葉子節點的赫夫曼樹的節點總數為2n-1,可以結合樹的度為n-1自己證明。
HT = (HuffmanTree)malloc((m+1)*sizeof(HTNode)); //數組首元素不使用,故多分配一個空間
p = HT + 1;
for(i=1;i<=n;++i,++p,++w) //n個葉子節點初始化
{
p->weight = *w;
p->lchild = 0;
p->rchild = 0;
p->parent = 0;
}
for(;i<=m;++i,++p) //非葉子節點初始化
{
p->weight = 0;
p->lchild = 0;
p->rchild = 0;
p->parent = 0;
}
for(i=n+1;i<=m;++i) //對非葉子節點重新計算
{
SelectMinNode(HT, i-1, i1, i2);
HT[i1].parent = i;
HT[i2].parent = i;
HT[i].lchild = i1;
HT[i].rchild = i2;
HT[i].weight = HT[i1].weight + HT[i2].weight ;
}
///從葉子節點到根節點求赫夫曼編碼
char* cd;
int start, c, f;
HC = (HuffmanCode)malloc((n+1)*sizeof(char*));//分配字元指針數組,同樣多分配一個
cd = (char*)malloc(n*sizeof(char)); //零時變數,用於存儲當前葉子節點的赫夫曼編碼
cd[n-1] = '\0';
for(int 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));
StrCopy(HC[i], cd, start); //將存儲的編碼給HC的第i個數組
}
free(cd);
}
void PrintHuffmanCode(HuffmanTree HT, HuffmanCode HC, int n) //列印各節點的赫夫曼編碼
{
HuffmanCode p;
for(int i=1; i<=n; i++)
{
p = HC;
printf("The weight %d HuffmanCode is: ", HT[i]);
while(*p[i]!='\0')
{
printf("%c",*p[i]);
p[i]++;
}
printf("\n");
}
}
void main()
{
int n = 8;
HuffmanTree HT;
HuffmanCode HC;
int a[8] = {5, 29, 7, 8, 14, 23, 3, 11};//信號源的概率分布,即P={p0, p1,…, pK-1}
HuffmanCoding(HT, HC, a, n);
PrintHuffmanCode(HT, HC, n);
system("pause");}
㈤ 哈夫曼編碼的C語言源代碼
/*文件名:exp7-6.cpp*/
#include <stdio.h>
#include <string.h>
#define N 50 /*葉子結點數*/
#define M 2*N-1 /*樹中結點總數*/
typedef struct
{
char data[5]; /*結點值*/
int weight; /*權重*/
int parent; /*雙親結點*/
int lchild; /*左孩子結點*/
int rchild; /*右孩子結點*/
} HTNode;
typedef struct
{
char cd[N]; /*存放哈夫曼碼*/
int start;
} HCode;
void CreateHT(HTNode ht[],int n)
{
int i,k,lnode,rnode;
int min1,min2;
for (i=0;i<2*n-1;i++) /*所有結點的相關域置初值-1*/
ht[i].parent=ht[i].lchild=ht[i].rchild=-1;
for (i=n;i<2*n-1;i++) /*構造哈夫曼樹*/
{
min1=min2=32767; /*lnode和rnode為最小權重的兩個結點位置*/
lnode=rnode=-1;
for (k=0;k<=i-1;k++)
if (ht[k].parent==-1) /*只在尚未構造二叉樹的結點中查找*/
{
if (ht[k].weight<min1)
{
min2=min1;rnode=lnode;
min1=ht[k].weight;lnode=k;
}
else if (ht[k].weight<min2)
{
min2=ht[k].weight;rnode=k;
}
}
ht[lnode].parent=i;ht[rnode].parent=i;
ht[i].weight=ht[lnode].weight+ht[rnode].weight;
ht[i].lchild=lnode;ht[i].rchild=rnode;
}
}
void CreateHCode(HTNode ht[],HCode hcd[],int n)
{
int i,f,c;
HCode hc;
for (i=0;i<n;i++) /*根據哈夫曼樹求哈夫曼編碼*/
{
hc.start=n;c=i;
f=ht[i].parent;
while (f!=-1) /*循序直到樹根結點*/
{
if (ht[f].lchild==c) /*處理左孩子結點*/
hc.cd[hc.start--]='0';
else /*處理右孩子結點*/
hc.cd[hc.start--]='1';
c=f;f=ht[f].parent;
}
hc.start++; /*start指向哈夫曼編碼最開始字元*/
hcd[i]=hc;
}
}
void DispHCode(HTNode ht[],HCode hcd[],int n)
{
int i,k;
int sum=0,m=0,j;
printf(" 輸出哈夫曼編碼:\n"); /*輸出哈夫曼編碼*/
for (i=0;i<n;i++)
{
j=0;
printf(" %s:\t",ht[i].data);
for (k=hcd[i].start;k<=n;k++)
{
printf("%c",hcd[i].cd[k]);
j++;
}
m+=ht[i].weight;
sum+=ht[i].weight*j;
printf("\n");
}
printf("\n 平均長度=%g\n",1.0*sum/m);
}
void main()
{
int n=15,i;
char *str[]={"The","of","a","to","and","in","that","he","is","at","on","for","His","are","be"};
int fnum[]={1192,677,541,518,462,450,242,195,190,181,174,157,138,124,123};
HTNode ht[M];
HCode hcd[N];
for (i=0;i<n;i++)
{
strcpy(ht[i].data,str[i]);
ht[i].weight=fnum[i];
}
printf("\n");
CreateHT(ht,n);
CreateHCode(ht,hcd,n);
DispHCode(ht,hcd,n);
printf("\n");
}
以前寫的,你照著改下就行的.
㈥ 哈夫曼編碼和解碼c語言的源程序
|#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <malloc.h>
#define NULL 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define MAX_NUM 10000
#define MAX 60
typedef int Status;
typedef char **HuffmanCode;
typedef struct{
unsigned int weight;
unsigned int parent,lchild,rchild;
}HTNode,*HuffmanTree;
typedef struct{
HuffmanTree HT;
char *c;
int longth;
HuffmanCode HC;
}Huffman;
void Select(HuffmanTree HT,int end,int *s1,int *s2)
{
int i;
int min1=MAX_NUM;
int min2;
for (i=1;i<=end;i++)
{
if (HT[i].parent==0&&HT[i].weight<min1)
{
*s1=i;
min1=HT[i].weight;
}
}
min2=MAX_NUM;
for(i=1;i<=end;i++)
{
if(HT[i].parent==0&&(*s1!=i)&&min2>HT[i].weight)
{
*s2=i;
min2=HT[i].weight;
}
}
}
Huffman HuffmanCoding(Huffman Hfm)
{
/*---------------------------------*/
int i,n,m,s1,s2,start;
int c,f;
char *cd;
n=Hfm.longth;
if(n<=1) return Hfm;
m=2*n-1;
for(i=n+1;i<=m;++i)
{
Select(Hfm.HT,i-1,&s1,&s2);
Hfm.HT[s1].parent=i;
Hfm.HT[s2].parent=i;
Hfm.HT[i].lchild=s1;
Hfm.HT[i].rchild=s2;
Hfm.HT[i].weight=Hfm.HT[s1].weight+Hfm.HT[s2].weight;
}
/*------------------------------------------*/
Hfm.HC=(HuffmanCode)malloc((n+1)*sizeof(char *));
cd=(char *)malloc(n*sizeof(char));
cd[n-1]='\0';
for(i=1;i<=n;++i)
{
start=n-1;
for(c=i,f=Hfm.HT[i].parent;f!=0;c=f,f=Hfm.HT[f].parent)
{
if(c==Hfm.HT[f].lchild) cd[--start]='0';
else cd[--start]='1';
}
Hfm.HC[i]=(char *)malloc((n-start)*sizeof(char));
strcpy(Hfm.HC[i],&cd[start]);
}
free(cd);
return Hfm;
}
Huffman InputHuffman(Huffman Hfm)
{
int i,n;
clrscr();
printf("\n\n\t\t********************Initial*********************\n");
printf("\tThe chars and weights will be saved in the file \"hfmTree\"\n");
printf("Please input the number of the chars: ");
scanf("%d",&n);
Hfm.HT=(HuffmanTree)malloc((2*n)*sizeof(HTNode));
Hfm.c=(char *)malloc((n+1)*sizeof(char));
for(i=1;i<=n;i++)
{
printf("Please input the char: ");
scanf("%s",&Hfm.c[i]);
printf("Please input the weight of the char: ");
scanf("%d",&Hfm.HT[i].weight);
Hfm.HT[i].parent=0;
Hfm.HT[i].lchild=0;
Hfm.HT[i].rchild=0;
}
for(;i<=2*n-1;++i)
{
Hfm.HT[i].weight=0;
Hfm.HT[i].parent=0;
Hfm.HT[i].lchild=0;
Hfm.HT[i].rchild=0;
}
Hfm.longth=n;
return Hfm;
}
Huffman InitHuffman(Huffman Hfm)
{
int n,i;
FILE *fp;
fp=fopen("hfmTree","rt");
if(fp==NULL)
{
Hfm=InputHuffman(Hfm);
fp=fopen("hfmTree","wt");
fprintf(fp,"%d\n",Hfm.longth);
for(i=1;i<=Hfm.longth;i++)
fprintf(fp,"%c %d",Hfm.c[i],Hfm.HT[i].weight);
rewind(fp);
}
else
{
fscanf(fp,"%d\n",&n);
Hfm.c=(char *)malloc((n+1)*sizeof(char));
Hfm.HT=(HuffmanTree)malloc((2*n)*sizeof(HTNode));
for(i=1;i<=n;i++)
fscanf(fp,"%s %d",&Hfm.c[i],&Hfm.HT[i].weight);
for(i=1;i<=n;i++)
{
Hfm.HT[i].parent=0;
Hfm.HT[i].lchild=0;
Hfm.HT[i].rchild=0;
}
for(;i<=2*n-1;++i)
{
Hfm.HT[i].weight=0;
Hfm.HT[i].parent=0;
Hfm.HT[i].lchild=0;
Hfm.HT[i].rchild=0;
}
Hfm.longth=n;
}
fclose(fp);
Hfm=HuffmanCoding(Hfm);
return Hfm;
}
void Output(Huffman Hfm)
{
int i,n;
n=Hfm.longth;
printf("\n\n******************Output the code of the chars****************\n\n");
for(i=1;i<=n;i++)
{
printf("\n");
printf("Char: %c\t",Hfm.c[i]);
printf("Weight: %d\t",Hfm.HT[i].weight);
printf("Code: ");
puts(Hfm.HC[i]);
}
}
void Encoding(Huffman Hfm)
{
int i=0,j=0,n;
char ch[MAX];
FILE *fp,*ffp;
n=Hfm.longth;
printf("\n\n*******************Encoding**************************\n\n");
if((ffp=fopen("ToBeTran","rt"))==NULL)
{
printf("\nPlease input the sentence: ");
scanf("%s",&ch);
printf("\n");
fp=fopen("CodeFile","wt+");
}
else
{
fscanf(ffp,"%s",ch);
fclose(ffp);
}
while(ch[j])
{
for(i=1;i<=n;i++)
if(ch[j]==Hfm.c[i])
{
printf("%s",Hfm.HC[i]);
fprintf(fp,"%s",Hfm.HC[i]);
break;
}
j++;
}
rewind(fp);
fclose(fp);
}
void Decoding(Huffman Hfm)
{
HuffmanTree p;
int i,n;
int j=0;
char d[50];
FILE *fp;
n=Hfm.longth;
printf("\n\n******************Decoding************************\n\n");
if((fp=fopen("CodeFile","rt"))==NULL)
{
printf("Please input the code:");
scanf("%s",&d);
}
else
{
fscanf(fp,"%s",d);
fclose(fp);
}
printf("\nThe file is : ");
fp=fopen("TextFile","wt+");
while(d[j])
{
p=&Hfm.HT[2*n-1];
while(p->lchild||p->rchild)
{
if(d[j]=='0')
{ i=p->lchild; p=&Hfm.HT[i]; }
else
{ i=p->rchild; p=&Hfm.HT[i]; }
j++;
}
printf("%c",Hfm.c[i]);
fprintf(fp,"%c",Hfm.c[i]);
}
fclose(fp);
}
Huffman RebuildHuffman(Huffman Hfm)
{
int n,i;
FILE *fp;
fp=fopen("hfmTree","wt");
Hfm=InputHuffman(Hfm);
fprintf(fp,"%d\n",Hfm.longth);
for(i=1;i<=Hfm.longth;i++)
fprintf(fp,"%c %d",Hfm.c[i],Hfm.HT[i].weight);
rewind(fp);
fclose(fp);
Hfm=HuffmanCoding(Hfm);
return Hfm;
}
int main()
{
Huffman Hfm;
char choice='a';
Hfm=InitHuffman(Hfm);
while(choice!='q')
{
clrscr();
printf("\n\n\n\t\t*************************************\n\n");
printf("\t\t\ta. Encoding:\n\n");
printf("\t\t\tb. Decoding:\n\n");
printf("\t\t\tc. Print all codes:\n\n");
printf("\t\t\td. Rebuild the huffmantree:\n\n");
printf("\t\t\tq. Quit...\n\n");
printf("\n\t\t************************************\n\n");
printf("Please enter your choice: ");
scanf("%s",&choice);
switch(choice)
{
case 'a':
clrscr();
Encoding(Hfm);
printf("\n\n*******Please enter anykey to continue*******\n");
getch(); break;
case 'b':
clrscr();
Decoding(Hfm);
printf("\n\n*******Please enter anykey to continue********\n");
getch(); break;
case 'c':
clrscr();
Output(Hfm);
printf("\n\n*******Please enter anykey to continue********\n");
getch(); break;
case 'd':
clrscr();
Hfm=RebuildHuffman(Hfm);
printf("\n\n********************Initial*********************\n");
getch(); break;
case 'q':
break;
default:
printf(" Your choice is wrong!\n Please enter anykey to choice again!\n");
getch(); break;
}
}
return 0;
}
㈦ huffman編碼解碼的c語言實現
留個腳印,晚上回去看看
#include <iostream.h>
#include <iomanip.h>
#include <string.h>
#include <malloc.h>
#include <stdio.h>
//typedef int TElemType;
const int UINT_MAX=1000;
char str[50];
typedef struct
{
int weight,K;
int parent,lchild,rchild;
}HTNode,* HuffmanTree;
typedef char **HuffmanCode;
//-----------全局變數-----------------------
HuffmanTree HT;
HuffmanCode HC;
int w[50],i,j,n;
char z[50];
int flag=0;
int numb=0;
// -----------------求赫夫曼編碼-----------------------
struct cou{
char data;
int count;
}cou[50];
int min(HuffmanTree t,int i)
{ // 函數void select()調用
int j,flag;
int k=UINT_MAX; // 取k為不小於可能的值,即k為最大的權值1000
for(j=1;j<=i;j++)
if(t[j].weight<k&&t[j].parent==0)
k=t[j].weight,flag=j;
t[flag].parent=1;
return flag;
}
//--------------------slect函數----------------------
void select(HuffmanTree t,int i,int &s1,int &s2)
{ // s1為最小的兩個值中序號小的那個
int j;
s1=min(t,i);
s2=min(t,i);
if(s1>s2)
{
j=s1;
s1=s2;
s2=j;
}
}
// --------------演算法6.12--------------------------
void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n)
{ // w存放n個字元的權值(均>0),構造赫夫曼樹HT,並求出n個字元的赫夫曼編碼HC
int m,i,s1,s2,start;
//unsigned c,f;
int 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); // 釋放工作空間
}
//---------------------獲取報文並寫入文件---------------------------------
int InputCode()
{
//cout<<"請輸入你想要編碼的字元"<<endl;
FILE *tobetran;
if((tobetran=fopen("tobetran.txt","w"))==NULL)
{
cout<<"不能打開文件"<<endl;
return 0;
}
cout<<"請輸入你想要編碼的字元"<<endl;
gets(str);
fputs(str,tobetran);
cout<<"獲取報文成功"<<endl;
fclose(tobetran);
return strlen(str);
}
//--------------初始化赫夫曼鏈表---------------------------------
void Initialization()
{ int a,k,flag,len;
a=0;
len=InputCode();
for(i=0;i<len;i++)
{k=0;flag=1;
cou[i-a].data=str[i];
cou[i-a].count=1;
while(i>k)
{
if(str[i]==str[k])
{
a++;
flag=0;
}
k++;
if(flag==0)
break;
}
if(flag)
{
for(j=i+1;j<len;j++)
{if(str[i]==str[j])
++cou[i-a].count;}
}
}
n=len-a;
for(i=0;i<n;i++)
{ cout<<cou[i].data<<" ";
cout<<cou[i].count<<endl;
}
for(i=0;i<=n;i++)
{*(z+i)=cou[i].data;
*(w+i)=cou[i].count;
}
/* 原來未修改的初始化程序段:
flag=1;
int num;
int num2;
cout<<"下面初始化赫夫曼鏈表"<<endl<<"請輸入結點的個數n:";
cin>>num;
n=num;
w=(int*)malloc(n*sizeof(int));
z=(char*)malloc(n*sizeof(char));
cout<<"\n請依次輸入"<<n<<"個字元(字元型):"<<endl;
char base[2];
for(i=0;i<n;i++)
{
cout<<"第"<<i+1<<"個字元:"<<endl;
gets(base);
*(z+i)=*base;
}
for(i=0;i<=n-1;i++)
{
cout<<setw(6)<<*(z+i);
}
cout<<"\n請依次輸入"<<n<<"個權值:"<<endl;
for(i=0;i<=n-1;i++)
{
cout<<endl<<"第"<<i+1<<"個字元的權值:";
cin>>num2;
*(w+i)=num2;
}*/
HuffmanCoding(HT,HC,w,n);
//------------------------列印編碼-------------------------------------------
cout<<"字元對應的編碼為:"<<endl;
for(i=1;i<=n;i++)
{
puts(HC[i]);
}
//--------------------------將赫夫曼編碼寫入文件------------------------
cout<<"下面將赫夫曼編碼寫入文件"<<endl<<"...................."<<endl;
FILE *htmTree;
char r[]={' ','\0'};
if((htmTree=fopen("htmTree.txt","w"))==NULL)
{
cout<<"can not open file"<<endl;
return;
}
fputs(z,htmTree);
for(i=0;i<n+1;i++)
{
fprintf(htmTree,"%6d",*(w+i));
fputs(r,htmTree);
}
for(i=1;i<=n;i++)
{
fputs(HC[i],htmTree);
fputs(r,htmTree);
}
fclose(htmTree);
cout<<"已將字元與對應編碼寫入根目錄下文件htmTree.txt中"<<endl<<endl;
}
//---------------------編碼函數---------------------------------
void Encoding()
{
cout<<"下面對目錄下文件tobetran.txt中的字元進行編碼"<<endl;
FILE *tobetran,*codefile;
if((tobetran=fopen("tobetran.txt","rb"))==NULL)
{
cout<<"不能打開文件"<<endl;
}
if((codefile=fopen("codefile.txt","wb"))==NULL)
{
cout<<"不能打開文件"<<endl;
}
char *tran;
i=99;
tran=(char*)malloc(100*sizeof(char));
while(i==99)
{
if(fgets(tran,100,tobetran)==NULL)
{
cout<<"不能打開文件"<<endl;
break;
}
for(i=0;*(tran+i)!='\0';i++)
{
for(j=0;j<=n;j++)
{
if(*(z+j-1)==*(tran+i))
{
fputs(HC[j],codefile);
if(j>n)
{
cout<<"字元錯誤,無法編碼!"<<endl;
break;
}
}
}
}
}
cout<<"編碼工作完成"<<endl<<"編碼寫入目錄下的codefile.txt中"<<endl<<endl;
fclose(tobetran);
fclose(codefile);
free(tran);
}
//-----------------解碼函數---------------------------------
void Decoding()
{
cout<<"下面對根目錄下文件codefile.txt中的字元進行解碼"<<endl;
FILE *codef,*txtfile;
if((txtfile=fopen("txtfile.txt","w"))==NULL)
{
cout<<"不能打開文件"<<endl;
}
if ((codef=fopen("codefile.txt","r"))==NULL)
{
cout<<"不能打開文件"<<endl;
}
char *work,*work2,i2;
int i4=0,i,i3;
unsigned long length=10000;
work=(char*)malloc(length*sizeof(char));
fgets(work,length,codef);
work2=(char*)malloc(length*sizeof(char));
i3=2*n-1;
for(i=0;*(work+i-1)!='\0';i++)
{
i2=*(work+i);
if(HT[i3].lchild==0)
{
*(work2+i4)=*(z+i3-1);
i4++;
i3=2*n-1;
i--;
}
else if(i2=='0') i3=HT[i3].lchild;
else if(i2=='1') i3=HT[i3].rchild;
}
*(work2+i4)='\0';
fputs(work2,txtfile);
cout<<"解碼完成"<<endl<<"內容寫入根目錄下的文件txtfile.txt中"<<endl<<endl;
free(work);
free(work2);
fclose(txtfile);
fclose(codef);
}
//-----------------------列印編碼的函數----------------------
void Code_printing()
{
cout<<"下面列印根目錄下文件CodePrin.txt中編碼字元"<<endl;
FILE * CodePrin,* codefile;
if((CodePrin=fopen("CodePrin.txt","w"))==NULL)
{
cout<<"不能打開文件"<<endl;
return;
}
if((codefile=fopen("codefile.txt","r"))==NULL)
{
cout<<"不能打開文件"<<endl;
return;
}
char *work3;
work3=(char*)malloc(51*sizeof(char));
do
{
if(fgets(work3,51,codefile)==NULL)
{
cout<<"不能讀取文件"<<endl;
break;
}
fputs(work3,CodePrin);
puts(work3);
}while(strlen(work3)==50);
free(work3);
cout<<"列印工作結束"<<endl<<endl;
fclose(CodePrin);
fclose(codefile);
}
//-------------------------------列印解碼函數---------------------------------------------
void Code_printing1()
{
cout<<"下面列印根目錄下文件txtfile.txt中解碼字元"<<endl;
FILE * CodePrin1,* txtfile;
if((CodePrin1=fopen("CodePrin1.txt","w"))==NULL)
{
cout<<"不能打開文件"<<endl;
return;
}
if((txtfile=fopen("txtfile.txt","r"))==NULL)
{
cout<<"不能打開文件"<<endl;
return;
}
char *work5;
work5=(char*)malloc(51*sizeof(char));
do
{
if(fgets(work5,51,txtfile)==NULL)
{
cout<<"不能讀取文件"<<endl;
break;
}
fputs(work5,CodePrin1);
puts(work5);
}while(strlen(work5)==50);
free(work5);
cout<<"列印工作結束"<<endl<<endl;
fclose(CodePrin1);
fclose(txtfile);
}
//------------------------列印赫夫曼樹的函數-----------------------
void coprint(HuffmanTree start,HuffmanTree HT)
{
if(start!=HT)
{
FILE * TreePrint;
if((TreePrint=fopen("TreePrint.txt","a"))==NULL)
{cout<<"創建文件失敗"<<endl;
return;
}
numb++;//該變數為已被聲明為全局變數
coprint(HT+start->rchild,HT);
cout<<setw(5*numb)<<start->weight<<endl;
fprintf(TreePrint,"%d\n",start->weight);
coprint(HT+start->lchild,HT);
numb--;
fclose(TreePrint);
}
}
void Tree_printing(HuffmanTree HT,int w)
{
HuffmanTree p;
p=HT+w;
cout<<"下面列印赫夫曼樹"<<endl;
coprint(p,HT);
cout<<"列印工作結束"<<endl;
}
//------------------------主函數------------------------------------
void main()
{
char choice;
while(choice!='q')
{ cout<<"\n******************************"<<endl;
cout<<" 歡迎使用赫夫曼編碼解碼系統"<<endl;
cout<<"******************************"<<endl;
cout<<"(1)要初始化赫夫曼鏈表請輸入'i'"<<endl;
cout<<"(2)要編碼請輸入'e'"<<endl;
cout<<"(3)要解碼請輸入'd'"<<endl;
cout<<"(4)要列印編碼請輸入'p'"<<endl;
cout<<"(5)要列印赫夫曼樹請輸入't'"<<endl;
cout<<"(6)要列印解碼請輸入'y'"<<endl;
if(flag==0)cout<<"\n請先初始化赫夫曼鏈表,輸入'i'"<<endl;
cin>>choice;
switch(choice)
{
case 'i':
Initialization();
break;
case 'e':
Encoding();
break;
case 'd':
Decoding();
break;
case 'p':
Code_printing();
break;
case 't':
Tree_printing(HT,2*n-1);
break;
case 'y':
Code_printing1();
break;
default:
cout<<"input error"<<endl;
}
}
free(z);
free(w);
free(HT);
}