求高手修改程序———哈夫曼编、译码器

twlkyao
博客专家认证
2010-05-11 10:40:13
#include <iostream.h>
#include <iomanip.h>
#include <string.h>
#include <malloc.h>
#include <stdio.h>
using namespace std;
const int UINT_MAX = 10000;//无符号整型的最大值

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


typedef char **HuffmanCode;//动态分配数组存储哈夫曼编码表

//-----------全局变量-----------------------
HuffmanTree HT;
HuffmanCode HC;
int *w,i,j,n,t;
char *z;
int flag = 0;
int numb = 0;
// -----------------求哈夫曼编码-----------------------

int min(HuffmanTree t, int i)//功能有待商榷
{// 函数void select()调用
int j, flag;
int k = UINT_MAX; // 取k为不小于可能的值
for (j = 1; j <= i; j++)
if (t[j].weight < k && t[j].parent == 0)//t[j]是树的根结点
k = t[j].weight, flag = j;
t[flag].parent = 1;//给选中的根节点的双亲赋1,避免第2次查找该结点
return flag;
}

//--------------------slect函数----------------------
void select(HuffmanTree t, int i, int &s1, int &s2)
{// 在i个结点中选择2个权值最小的树的根结点序号,s1为最小的两个值中序号小的那个
int j;
s1 = min(t, i);
s2 = min(t, i);
if (s1 > s2)
{
j = s1;
s1 = s2;
s2 = j;
}
}

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;
HuffmanTree p;
char *cd;
if (n <= 1)
return ;
//检测结点数是否可以构成树
m = 2 * n - 1;//n个叶结点,m为结点总数
HT = (HuffmanTree)malloc((m + 1) *sizeof(HTNode)); // 0号单元未用
for (p = HT + 1, i = 1; i <= n; ++i, ++p, ++w)//叶子结点初始化
{
(*p).weight = *w;//p所指向的结构体中weight赋值w
(*p).parent = 0;
(*p).lchild = 0;
(*p).rchild = 0;
}
for (; i <= m; ++i, ++p)//生成结点的双亲赋初值
{
(*p).weight = 0;
(*p).parent = 0;
(*p).lchild = 0;
(*p).rchild = 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 = i;
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); // 释放工作空间
}//HuffanCoding

//--------------初始化哈夫曼树--------------------------------
//----------------输入字符集大小及n个字符及其权值,建立哈夫曼树,并存于hfmTree.txt中----------------------
void Initialization()
{
cout << "下面初始化哈夫曼链表" << endl << "请输入结点的个数n:"<<endl;
cin >> n;
w = (int*)malloc(n *sizeof(int));
z = (char*)malloc(n *sizeof(char));
cout << "请依次输入" << n << "个字符(字符型)\n(注意:必须以回车结束:)" <<endl;
for (i = 0; i < n; i++)
{
cout << "第" << i + 1 << "个字符:" << endl;
cin>>z[i];//输入字符存入字符数组Z中

}
cout << "请依次输入" << n << "个权值\n(注意:必须以回车结束):" << endl;
for (i = 0; i < n; i++)
{
cout << "第" << i + 1 << "个字符的权值:"<<endl;
cin>>w[i];//输入每个字符对应的权值存入权值数组w中
}
HuffmanCoding(HT, HC, w, n);//对输入的字符进行哈夫曼编码
//------------------------打印编码-------------------------------------------
cout << "字符对应的编码为:" << endl;
for (i = 1; i <= n; i++)
{
cout<<"字符"<<*(z+i-1)<<"的编码为"<<HC[i]<<endl;//输出字符对应的编码
}


//--------------------------将哈夫曼编码写入文件------------------------
cout << "下面将哈夫曼编码写入文件" << endl;
FILE *hfmTree;
char r[] =
{
' ', '\0'
};
hfmTree = fopen("hfmTree.txt", "w");
if (hfmTree == NULL)
{
cout << "不能打开hfmTree.txt文件" << endl;
return ;
}
fputs(z, hfmTree);//将z中的字符写入hfmTree指向的文件中
for(i = 1; i < n + 1; i++)
{
fputs(HC[i], hfmTree);
fputs(r, hfmTree);
//fputs(HC[i],hfmTree);//存的是编码?
}
fclose(hfmTree);
cout << "已将字符与对应编码写入根目录下文件hfmTree.txt中" << endl;
flag = 1;
}

//---------------------获取报文并写入文件---------------------------------

void InputChar ()
{
FILE *ToBeTran;
char str[100];
ToBeTran = fopen("ToBeTran.txt", "w");
if (ToBeTran == NULL)//有问题?
{
cout << "不能打开ToBeTran.txt文件" << endl;
return ;
}
cout << "请输入你想要编码的字符(串):" << endl;
cin>>str;
fputs(str, ToBeTran);
cout << "获取报文成功" << endl;
fclose(ToBeTran);
}

//---------------------编码函数---------------------------------
void Encoding()
{
InputChar ();
cout << "下面对目录下文件ToBeTran.txt中的字符进行编码" << endl;
FILE *ToBeTran, *CodeFile;
ToBeTran = fopen("ToBeTran.txt", "rb");
if (ToBeTran == NULL)
{
cout << "不能打开ToBeTran.txt文件" << endl;
}
CodeFile = fopen("CodeFile.txt", "w");//原来是"wb"
if (CodeFile == NULL)
{
cout << "不能打开CodeFile.txt文件" << endl;
}
char *tran;
i = 99;
tran = (char*)malloc(100 *sizeof(char));
while (i == 99)
{
if (fgets(tran, 100, ToBeTran) == NULL)
{
cout << "不能打开ToBeTran.txt文件" << endl;
break;
}
for (i = 0; tran [i] != '\0'; i++)
{
for (j = 1; j <= n; j++)
{
if (z [j - 1] == tran [i])
{
fputs(HC[j], CodeFile);
if (j > n)
{
cout << "字符错误,无法编码!" << endl;
break;
}
}
}
}
}
cout << "编码工作完成" << endl << "编码写入目录下的CodeFile.txt中" <<endl;
fclose(ToBeTran);
fclose(CodeFile);
free(tran);
}


//-----------------译码函数---------------------------------
void Decoding()
{
cout << "下面对根目录下文件CodeFile.txt中的字符进行译码" << endl;
FILE *codef, *txtfile;
txtfile = fopen("TextFile.txt", "w");
if (txtfile == NULL)
{
cout << "不能打开TextFile.txt文件" << endl;
}
codef = fopen("CodeFile.txt", "r");
if (codef == NULL)
{
cout << "不能打开CodeFile.txt文件" << 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++)//有待思考?是0还是NULL
{
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';//有待思考'\0'
fputs(work2, txtfile);
cout << "译码完成" <<endl<< "内容写入根目录下的文件TextFile.txt中" <<endl;
//cout <<"译码为:"<< work2<<endl;//输出译码
free(work);
free(work2);
fclose(txtfile);
fclose(codef);
}
//-----------------------打印编码的函数----------------------
void Code_printing()
{
cout << "下面打印根目录下文件CodePrin.txt中编码字符" << endl;
FILE *CodePrin, *codefile;
CodePrin = fopen("CodePrin.txt", "w");
if (CodePrin == NULL)
{
cout << "不能打开CodePrin.txt文件" << endl;
return ;
}
codefile = fopen("CodeFile.txt", "r");
if (codefile == NULL)
{
cout << "不能打开CodeFile.txt文件" << endl;
return ;
}
char *work3;
work3 = (char*)malloc(51 *sizeof(char));
//do
//{
if (fgets(work3, 51, codefile) == NULL)
{
cout << "不能读取CodeFile.txt文件" << endl;
//break;
}
fputs(work3, CodePrin);
cout<<work3<<endl;
//}while (strlen(work3) == 50);
free(work3);
int iNum=2,num=2;
while((num=fscanf(codefile,"%d",iNum))!=0)//有待思考'\0'
{
printf("%d",iNum);
fprintf(CodePrin,"%d",iNum);
}
cout << "打印工作结束" << endl << endl;
fclose(CodePrin);
fclose(codefile);
}
//打印编码有问题


//------------------------打印哈夫曼树的函数-----------------------
void coprint(HuffmanTree start, HuffmanTree HT)//start为形参
{
if (start != HT)
{
FILE *TreePrint;
TreePrint = fopen("TreePrint.txt", "a");
if (TreePrint == NULL)
{
cout << "创建TreePrint.txt文件失败" << 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;
}
//------------------------主函数------------------------------------
int main()
{
char choice;
while (choice != 'q')
{
cout << "******************************" << 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)要离开请输入'q'" << endl;
if(flag==0)cout<<"第一次使用时请先初始化哈夫曼链表,输入'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 'q':cout<<"****感谢适用本系统,再见!****"<<endl;break;
default:cout << "输入错误,请重新输入" << endl;
}
}
free(z);
free(w);
free(HT);
return 0;
}






以上程序要求
一个完整的系统已具有以下功能:
(1)I:初始化。从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件hfmTree中。
(2)E:编码。利用已建好的哈夫曼树(如不在内存,则从文件hfmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果粗如文件CodeFile中。
(3)D:译码。利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入TextFile中。
(4)P:印代码文件。将文件CodeFile以紧凑格式显示在终端上,每行50个代码。同时将此字符形式的编码文件写入文件CodePrin中。
(5)T:印哈夫曼树。将已在内存中的哈夫曼树以直观的方式(树或凹凸表形式)显示在终端上,同时将此字符形式的哈夫曼树写入TreePrin中。




目前的问题是:(1):hfmTree中不能存哈夫曼树HT,暂且存的HC,
(2):打印代码文件出现的全是2,且不会停止

希望高手帮忙看看,小弟不胜感激
...全文
344 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
r11222 2010-05-11
  • 打赏
  • 举报
回复
#include<iostream.h>
#include<stdlib.h>
#include<process.h>
#include<conio.h>
#include<stdio.h>
#define ERROR 0
#define OK 1
typedef bool Status;
#define SIZE 20
typedef FILE *PFILE;
typedef char *ElemType;
typedef struct HTNode//哈夫曼树结点类型
{int weight;//结点的权值
int parent,lchild,rchild;
//结点的双亲parent,结点的左子树lchild,结点的右子树rchild
}*PHTNode;
struct HuffmanTree//哈夫曼树类型
{HTNode *HT;//哈夫曼树
ElemType ch;//哈夫曼树的字符集
int n;//哈夫曼树的字符集个数
};
Status OpenWriteFile(PFILE &fp,char string[SIZE])
//打开写的文件
{
if(!(fp=fopen(string,"wb"))){
cout<<"文件打开失败"<<endl;
exit(ERROR);
cout<<"Press any key to exit"<<endl;
getch();
}
return OK;
}
Status OpenReadFile(PFILE &fp,char string[SIZE])
//打开读的文件
{
if(!(fp=fopen(string,"rb "))){
cout<<"文件打开失败"<<endl;
cout<<"Press any key to exit"<<endl;
getch();
exit(ERROR);
}
return OK;
}
Status PrintFile(char string[SIZE])
//输出文件名为string的字符
{
FILE *fp;char c;
OpenReadFile(fp,string);
while(!feof(fp)){
for(int i=1;i<=50&&!feof(fp);i++){
c=getc(fp);
cout<<c;
}
cout<<endl;
}
fclose(fp);
return OK;
}
Status initHTree(HuffmanTree &T,int n)
//初始化一个n个字符集的哈夫曼树
{
T.n=n;
if(!(T.HT=new HTNode[2*T.n])){
cout<<"分配哈夫曼树的存储空间失败"<<endl;
exit(ERROR);
}
if(!(T.ch=new char[T.n+1])){
cout<<"分配字符集的存储空间失败"<<endl;
exit(ERROR);
}
return OK;
}
Status DestroyHTree(HuffmanTree &T)
//销毁哈夫曼树
{
delete(T.HT);
delete(T.ch);
return OK;
}
Status Select(int &s1,int &s2,int n,PHTNode H)
//从二叉树位置从0~n集合中找到2个根结点的权值最小的位置
{
int i,leap=0;
for(i=1;i<=n;i++)
if(!H[i].parent)
if(leap){
if(H[i].weight<H[s1].weight) s1=i;
}
else {s1=i;leap=1;}
leap=0;H[s1].parent=1;
for(i=1;i<=n;i++)
if(!H[i].parent)
if(leap){
if(H[i].weight<H[s2].weight) s2=i;
}
else {s2=i;leap=1;}
return OK;
}
Status CreateHTree()
//创建哈夫曼树并把结果保存在string为文件名的文件里
{
int i,s1,s2;FILE *fp,*cfp;char c,string[SIZE];
HuffmanTree T;int n;
cout<<"请输入字符集的大小(n):";
cin>>n;
initHTree(T,n);
cout<<"请输入字集的保存路径\\名称:";
cin>>string;
OpenReadFile(cfp,string);
cout<<"请输入字符集对应的权值:"<<endl;
for(i=1;i<=T.n;i++){
c=getc(cfp);
cout<<c<<":";
T.ch[i]=c;
cin>>T.HT[i].weight;
T.HT[i].parent=0;
T.HT[i].rchild=0;
T.HT[i].lchild=0;
}
for(;i<2*T.n;i++){
T.HT[i].weight=0;
T.HT[i].parent=0;
T.HT[i].rchild=0;
T.HT[i].lchild=0;
}
for(i=T.n+1;i<2*T.n;i++){
Select(s1,s2,i-1,T.HT);
T.HT[i].lchild=s1;T.HT[i].rchild=s2;
T.HT[s1].parent=i;T.HT[s2].parent=i;
T.HT[i].weight=T.HT[s1].weight+T.HT[s2].weight;
}
cout<<"请输入哈夫曼树的保存路径\\名称:";
cin>>string;
OpenWriteFile(fp,string);
fwrite(&T.n,sizeof(int),1,fp);
fwrite(T.HT,sizeof(HTNode),2*T.n,fp);
fwrite(T.ch,sizeof(char),T.n+1,fp);
fclose(fp);fclose(cfp);DestroyHTree(T);
return OK;
}
Status HEncoding(char string[SIZE])
//哈夫曼编码,并把结果保存在string文件中
{
HuffmanTree T;
FILE *fp,*hfp,*cfp;
int i,j,k;
char ch[SIZE],c,*cd;
cout<<"请输入保存哈夫曼树的保存路径\\名称:";
cin>>ch;
OpenReadFile(hfp,ch);
cout<<"请输入要编码文件的保存路径\\名称:";
cin>>ch;
OpenReadFile(fp,ch);
cout<<"请输入代码文件的保存路径\\名称:";
cin>>string;
OpenWriteFile(cfp,string);
fread(&T.n,sizeof(int),1,hfp);
if(!(cd=new char[T.n])){
cout<<"编码工作空间分配失败"<<endl;
exit(ERROR);
}
initHTree(T,T.n);
fread(T.HT,sizeof(HTNode),2*T.n,hfp);
fread(T.ch,sizeof(char),T.n+1,hfp);
c=getc(fp);
while(!feof(fp)){
for(i=1;i<=T.n&&c!=T.ch[i];i++);
j=T.n;k=i; while(T.HT[k].parent)
if(T.HT[T.HT[k].parent].lchild==k){
cd[--j]='0'; k=T.HT[k].parent;
}
else{
cd[--j]='1'; k=T.HT[k].parent;
}
for(j;j<T.n;j++)
putc(cd[j],cfp);
c=getc(fp);
}
DestroyHTree(T);
delete(cd);
fclose(cfp);
fclose(hfp);
fclose(fp);
return OK;
}
Status HDecoding(char string[SIZE])
//哈夫曼译码,并把结果保存在string文件中
{HuffmanTree T;
char ch[SIZE],c;
FILE *fp,*hfp,*cfp;
cout<<"请输入保存哈夫曼树的保存路径\\名称:";
cin>>ch;
OpenReadFile(hfp,ch);
fread(&T.n,sizeof(int),1,hfp);
initHTree(T,T.n);
fread(T.HT,sizeof(HTNode),2*T.n,hfp);
fread(T.ch,sizeof(char),T.n+1,hfp);
void PrintHTree(HuffmanTree T);
cout<<"请输入代码文件的保存路径\\名称:";
cin>>ch;
OpenReadFile(cfp,ch);
cout<<"请输入译码文件的保存路径\\名称:";
cin>>string;
OpenWriteFile(fp,string);
c=getc(cfp);
while(!feof(cfp)){
for(int i=2*T.n-1;T.HT[i].lchild&&!feof(cfp);c=getc(cfp))
if(c=='0')i=T.HT[i].lchild;
else i=T.HT[i].rchild;
putc(T.ch[i],fp);
}
fclose(cfp);
fclose(hfp);
fclose(fp);
DestroyHTree(T);
return OK;
}
void main()
{char string[SIZE],c='A';
do{system("cls");
cout<<"*******************************************************************************"<<endl;
cout<<" 本程序的命令:(1)创建哈夫曼树C;\n";
cout<<" (2)对指定的文件现行编码E;\n";
cout<<" (3)对指定的代码进行译码D;\n";
cout<<" (4)退出程序Q."<<endl;
cout<<"*******************************************************************************"<<endl;
cout<<"请输入命令(C,E,D,Q):";
cin>>c;
switch(c){
case 'C':CreateHTree(); break;
case 'E':HEncoding(string);cout<<"哈夫曼编码的结果:"<<endl;PrintFile(string);break;
case 'D':HDecoding(string);cout<<"哈夫曼译码的结果:"<<endl;PrintFile(string);break;
}
cout<<"请输入任意键继续运行程序"<<endl;
getch();
}while(c!='Q');
}
twlkyao 2010-05-11
  • 打赏
  • 举报
回复
不是啊
r11222 2010-05-11
  • 打赏
  • 举报
回复
韶关的吗。。。。

64,648

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧