易网时代-编程资源站
Welcome
微信登录
编程资源
图片资源库
蚂蚁家优选
PDF转换器
软件资源
软件开发
、
小程序制作
、
系统集成与运维
、
空间租用
、
硬件开发
、
视频监控
、
技术咨询与支持
——联系电话:0311-88999002/88999003
首页
/
操作系统
/
Linux
/
C++ 哈弗曼编码的实现与反编码
C++ 哈弗曼编码的实现与反编码
#include<iostream>
#include<stdlib.h>
#include<string.h>
using
namespace
std;
typedef
struct
{
int
weight;
int
parent,lchild,rchild;
int
asc;
}HTNode,*HuffmanTree;
//定义赫夫曼存储结构
struct
node{
int
ASCII;
int
n;
};
struct
node a[127];
struct
node w[127];
//一些全局变量
int
count;
HTNode H_T[250];
char
** HC;
char
filename[20];
//函数声明
void
menu1();
//菜单1
HuffmanTree HeapSort(HuffmanTree HT,
int
length);
//堆排序
void
MinHeapify(HuffmanTree HT,
int
k,
int
len);
//调整成一个小顶堆
void
buildMinHeap(HuffmanTree HT,
int
len);
//建一个小顶堆
void
swap(HTNode &t1,HTNode &t2);
//交换两结构体
void
savefile();
//把输入的英文文章保存到文件
void
loadfile();
//从文件中读取文章
HuffmanTree CreateHuffman(HuffmanTree &HT,
struct
node *w,
int
n);
//建立赫夫曼数并存入文件
void
BianMa(HuffmanTree HT,
int
n );
//字符编码
void
BianMa_all(HuffmanTree HT,
char
**HC,
char
*filename);
//整篇文章编码
int
loadfile2();
//从文件读入文章
void
JieMa();
//解码
//主函数
void
main()
{
char
s;
while
(s!=
"0"
)
{
system(
"cls"
);
cout<<
"/n/n/n"
;
cout<<
"/t/t/t/t赫夫曼编码/译码器"
<<endl<<endl<<endl<<endl<<endl;
cout<<
"/t/t/t/t 1.编码"
<<endl<<endl<<endl<<endl;
cout<<
"/t/t/t/t 2.译码"
<<endl<<endl<<endl<<endl;
cout<<
"/t/t/t/t 0.退出"
<<endl<<endl<<endl<<endl;
cout<<
"/t请输入0—2进行选择,按回车确认"
;
cin>>s;
switch
(s)
{
case
"1"
: menu1();
break
;
case
"2"
:
{
system(
"cls"
);
JieMa();
system(
"pause"
);
break
;
}
}
}
}
//菜单1
void
menu1(){
char
s;
int
i;
int
a;
char
c;
char
fpname[20]=
"article.txt"
;
HuffmanTree HT;
while
(s!=
"0"
){
system(
"cls"
);
cout<<
"/n/t/t/t/t编码界面"
;
cout<<
"/n/n/n/t/t/t/t1.输入英文文章"
<<endl;
cout<<
"/n/n/t/t/t/t2.从文件中读入文章"
<<endl;
cout<<
"/n/n/t/t/t/t0.返回上一层"
<<endl;
cout<<
"/n/t请输入0—2进行选择,按回车确认"
;
cin>>s;
switch
(s){
case
"1"
:
system(
"cls"
);
savefile();
loadfile();
CreateHuffman(HT,w,count);
BianMa(HT,count);
BianMa_all(HT,HC,fpname);
system(
"cls"
);
cout<<
"出现字符种类共计:"
;
cout<<count<<endl;
for
(i=1;i<=count;i++)
{ a=HT[i].asc;
c=(
char
)a;
cout<<
"________________________________________________________________________________"
<<endl;
cout<<
"/t/t/t字符:"
;
cout<<c<<endl;
cout<<
"/t/t/tASCII码:"
;
cout<<a<<endl;
cout<<
"/t/t/t频数:"
;
cout<<HT[i].weight<<endl;
cout<<
"/t/t/t赫夫曼编码:"
;
cout<<HC[i]<<endl;
}
cout<<
"________________________________________________________________________________"
;
cout<<
"/n/t/t整篇文章的编码已存入文件“赫夫曼编码.txt”"
<<endl;
system(
"pause"
);
break
;
case
"2"
:
system(
"cls"
);
if
(loadfile2())
{ system(
"pause"
);
return
;}
CreateHuffman(HT,w,count);
BianMa(HT,count);
BianMa_all(HT,HC,filename);
system(
"cls"
);
cout<<
"出现字符种类共计:"
;
cout<<count<<endl;
for
(i=1;i<=count;i++)
{ a=HT[i].asc;
c=(
char
)a;
cout<<
"________________________________________________________________________________"
<<endl;
cout<<
"/t/t/t字符:"
;
cout<<c<<endl;
cout<<
"/t/t/tASCII码:"
;
cout<<a<<endl;
cout<<
"/t/t/t频数:"
;
cout<<HT[i].weight<<endl;
cout<<
"/t/t/t赫夫曼编码:"
;
cout<<HC[i]<<endl;
}
cout<<
"________________________________________________________________________________"
;
cout<<
"/n/t/t整篇文章的编码已存入文件“赫夫曼编码.txt”"
<<endl;
system(
"pause"
);
break
;
}
}
}
//交换结构体
void
swap(HTNode &t1,HTNode &t2)
{
HTNode m;
m = t1;
t1 = t2;
t2 = m;
}
//从键盘输入文章并保存
void
savefile(){
FILE
*fp;
char
article;
if
((fp=fopen(
"article.txt"
,
"w"
))==NULL){
printf(
"打开文件不成功!"
);
exit(0);
}
cout<<
"请输入英文文章,以#结束:"
;
getchar();
article=getchar();
while
(article!=
"#"
){
fputc(article,fp);
article=getchar();
}
fclose(fp);
}
//从文件读取文章,并统计字符出现频数
void
loadfile(){
FILE
*fp;
char
ch;
int
i,k,j=0;
count=0;
for
(i=0;i<=127;i++)
//把所有字符的ascii码存在数组
{ a[i].ASCII=i;
a[i].n=0;
}
if
((fp=fopen(
"article.txt"
,
"r"
))==NULL){
printf(
"打开文件不成功!"
);
exit(0);
}
ch=fgetc(fp);
k=(
int
)ch;
a[k].n++;
while
(!feof(fp)){
ch=fgetc(fp);
k=(
int
)ch;
a[k].n++;
}
fclose(fp);
for
(i=0;i<=127;i++)
//统计字符种类总数
{
ch=(
char
)i;
if
(a[i].n){
count++;
}
}
for
(i=0;i<=127;i++)
{
for
(;j<count;)
{
if
(a[i].n)
{
w[j].n=a[i].n;
w[j].ASCII=a[i].ASCII;
j++;
break
;
}
else
break
;
}
}
}
//调整为小顶堆
void
MinHeapify(HuffmanTree HT,
int
k,
int
len)
{
int
left=k*2;
int
right=k*2+1;
int
large;
int
l=len;
large = k;
if
(left<=l&&HT[left].weight<HT[large].weight)
large = left;
if
(right<=l&& HT[right].weight<HT[large].weight)
large=right;
if
(large!=k)
{
swap(HT[k],HT[large]);
MinHeapify(HT,large,l);
}
}
//建立小顶堆
void
buildMinHeap(HuffmanTree HT,
int
len)
{
int
i;
for
(i=len/2;i>=1;i--)
{
MinHeapify(HT,i,len);
}
}
//堆排序
HuffmanTree HeapSort(HuffmanTree HT,
int
length)
{
int
i;
int
l=length;
buildMinHeap(HT,length);
for
(i=length;i>= 2;i--)
{
swap(HT[1],HT[i]);
length--;
MinHeapify(HT,1,length);
}
return
HT;
}
//建立赫夫曼数
HuffmanTree CreateHuffman(HuffmanTree &HT,
struct
node *w,
int
n)
{
int
i,m,s1,s2,k1,k2,j,x,a;
FILE
*fp,*fp2;
if
(n<=1)
return
HT;
m=2*n-1;
HT=(HuffmanTree)malloc((m+1)*
sizeof
(HTNode));
//0不用
for
(i=1,j=0;i<=n;i++,j++)
{ HT[i].asc=w[j].ASCII;
HT[i].weight=w[j].n;
HT[i].parent=0;
HT[i].lchild=0;
HT[i].rchild=0;
}
for
(;i<=m;i++)
{ a=250+i;
HT[i].asc=a;
//父亲节点的asc可以是大于127的任意值
HT[i].weight=0;
HT[i].parent=0;
HT[i].lchild=0;
HT[i].rchild=0;
}
for
(i=1;i<=n;i++){
H_T[i].asc=HT[i].asc;
H_T[i].parent=HT[i].parent;
H_T[i].lchild=HT[i].lchild;
H_T[i].rchild=HT[i].rchild;
H_T[i].weight=HT[i].weight;
}
for
(i=n+1,x=n;i<=m;i++,x--)
{
HeapSort(H_T,x);
k1=H_T[x].asc;
k2=H_T[x-1].asc;
for
(j=1;j<=127;j++)
{
if
(HT[j].asc==k1)
{ s1=j;
break
;}
}
for
(j=1;j<=127;j++)
{
if
(HT[j].asc==k2)
{ s2=j;
break
;}
}
HT[s2].parent=i;
HT[s1].parent=i;
HT[i].lchild=s1;
HT[i].rchild=s2;
HT[i].weight=HT[s1].weight+HT[s2].weight;
H_T[x-1].asc=HT[i].asc;
H_T[x-1].lchild=HT[i].lchild;
H_T[x-1].parent=HT[i].parent;
H_T[x-1].rchild=HT[i].rchild;
H_T[x-1].weight=HT[i].weight;
}
if
((fp2=fopen(
"count.txt"
,
"w"
))==NULL)
//保存赫夫曼树
{
cout<<
"文件打开不成功!"
<<endl;
exit(0);
}
fputc(count,fp2);
if
((fp=fopen(
"HuffmanTree.dat"
,
"wb"
))==NULL)
{ cout<<
"文件打开不成功!"
<<endl;
exit(0);
}
for
(i=1;i<=(2*count-1);i++){
fwrite(&HT[i],
sizeof
(HTNode),1,fp);
}
fclose(fp);
fclose(fp2);
return
HT;
}
//逆向编码
void
BianMa(HuffmanTree HT,
int
n){
char
*cd,temp;
int
c,f,i,j,len,p,q;
cd=(
char
*)malloc(n*
sizeof
(
char
));
HC=(
char
* *)malloc(n*
sizeof
(
char
*));
for
(i=1;i<=n;i++){
for
(c=i,f=HT[i].parent,j=0;f!=0;c=f,f=HT[f].parent,j++)
{
if
(HT[f].lchild==c) cd[j]=
"0"
;
else
cd[j]=
"1"
;
if
(HT[f].parent==0)
cd[j+1]=
"/0"
;
}
len=strlen(cd);
for
(p=0,q=len-1;p<=q;p++,q--)
{
temp=cd[q];
cd[q]=cd[p];
cd[p]=temp;
}
cd[len]=
"/0"
;
HC[i]=(
char
*)malloc((len+10)*
sizeof
(
char
));
strcpy(HC[i],cd);
}
}
//整篇文章编码,并存入文件
void
BianMa_all(HuffmanTree HT,
char
**HC,
char
*filename){
char
ch;
int
k,i;
FILE
*fp,*fp2;
char
code[100];
if
((fp=fopen(filename,
"r"
))==NULL){
printf(
"打开文件不成功!"
);
exit(0);
}
if
((fp2=fopen(
"赫夫曼编码.txt"
,
"w"
))==NULL){
printf(
"打开文件不成功!"
);
exit(0);
}
ch=fgetc(fp);
k=(
int
)ch;
while
(!feof(fp))
{
for
(i=1;i<=count;i++)
{
if
(k==HT[i].asc)
strcpy(code,HC[i]);
}
fputs(code,fp2);
ch=fgetc(fp);
k=(
int
)ch;
}
fclose(fp);
fclose(fp2);
}
void
JieMa(){
int
i,k,a,t,n=0;
FILE
*fp1,*fp2,*fp3;
char
ch,c;
HuffmanTree ht;
if
((fp3=fopen(
"count.txt"
,
"r"
))==NULL)
//从文件读出字符总数
{
printf(
"打开文件不成功!"
);
exit(0);
}
n=fgetc(fp3);
ht=(HuffmanTree)malloc(2*n*
sizeof
(HTNode));
if
((fp1=fopen(
"赫夫曼编码.txt"
,
"r"
))==NULL)
{
printf(
"打开文件不成功!"
);
exit(0);
}
if
((fp2=fopen(
"HuffmanTree.dat"
,
"rb"
))==NULL)
{ cout<<
"文件打开不成功!"
<<endl;
exit(0);
}
for
(i=1;i<=2*n-1;i++)
fread(&ht[i],
sizeof
(HTNode),1,fp2);
for
(i=1;i<=2*n-1;i++)
{
if
(ht[i].parent==0){t=k=i;
break
;}
}
ch=fgetc(fp1);
while
(!feof(fp1)){
if
(ch==
"0"
)
{
k=ht[k].lchild;
if
(ht[k].lchild==0)
{a=ht[k].asc;
c=(
char
)a;
printf(
"%c"
,c);;
k=t;
}
}
if
(ch==
"1"
)
{
k=ht[k].rchild;
if
(ht[k].lchild==0)
{ a=ht[k].asc;
c=(
char
)a;
printf(
"%c"
,c);
k=t;
}
}
ch=fgetc(fp1);
}
fclose(fp1);
fclose(fp2);
}
//读取文件中的文章,可自己选择文件
int
loadfile2(){
FILE
*fp;
char
ch;
int
i,k,j=0;
count=0;
for
(i=0;i<=127;i++)
{ a[i].ASCII=i;
a[i].n=0;
}
cout<<
"/n/n/n/t/t/t请输入你要打开的文件名:"
;
cin>>filename;
if
((fp=fopen(filename,
"r"
))==NULL){
printf(
"打开文件不成功!"
);
return
1;
}
ch=fgetc(fp);
k=(
int
)ch;
a[k].n++;
while
(!feof(fp)){
ch=fgetc(fp);
k=(
int
)ch;
a[k].n++;
}
fclose(fp);
for
(i=0;i<=127;i++){
ch=(
char
)i;
if
(a[i].n){
count++;
}
}
for
(i=0;i<=127;i++)
{
for
(;j<count;)
{
if
(a[i].n)
{
w[j].n=a[i].n;
w[j].ASCII=a[i].ASCII;
j++;
break
;
}
else
break
;
}
}
return
0;
}
收藏该网址
版权所有©石家庄振强科技有限公司2024
冀ICP备08103738号-5
网站地图