⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 text5-2.cpp

📁 huffman编码译码器
💻 CPP
字号:
#include<iostream>
#include<string.h>
#include <stdio.h>
#include <stdlib.h>
#include<malloc.h>
using namespace std;
typedef struct FreOfCh{//用来存储用户输入的字符——频度集
	char word;
	int weight;
};


typedef struct {
	int weight;
    int parent,lchild,rchild;
	char word;
	int mark;
}HTNode,*HuffmanTree;



typedef char **HuffmanCode;

typedef struct codefilenode{//存入该文件的节点类型。实际上只是用来存贮在文件的一个媒介结构体
	char word;
	char* code;
};


#define STACK_INIT_STZE 100//存储空间初始分配量
#define STACKINCREMENT 50//存储空间分配增量
typedef struct{
	HuffmanTree *base;
	HuffmanTree *top;
	int stacksize;//当前已分配的存储空间
}SqStack;

//===========================三级调用函数===========================


void InitStack(SqStack &S){//构造一个空栈
	S.base=(HuffmanTree *)malloc(STACK_INIT_STZE*sizeof(HTNode));
	//if(!S.base)exit(OVERFLOW);
	S.top=S.base;
	S.stacksize=STACK_INIT_STZE;
}//InitStack

void Push(SqStack &S,HuffmanTree e){//入栈
	*S.top++=e;
}//Push

void Pop(SqStack &S,HuffmanTree &e){//出栈
	//if(S.top==S.base)return ERROR;
	e=*(S.top-1);
	S.top=S.top-1;
}//Pop
 

//===================================二级调用函数==================================


int  ReInitFileOfHuf(int &n){//建立用户输入字符频度集合,存入user文件中
	                   //返回的值为用户输入字符的个数n
	cout<<"请输入字符总个数 !";
    cin>>n;
	struct FreOfCh *usr;
	usr=new FreOfCh[n];
	cout<<"请输入所有字符!";
	char ch;int i=0;
	ch=getchar();
	ch=getchar();
	while(i!=n){
		usr[i].word=ch;
		ch=getchar();
		i++;
	}
	cout<<"请输入相应的权值!";
	int m;
	i=0;
	cin>>m ;
	cout<<"请确认信息"<<endl;
	while(i!=n ){
		usr[i].weight=m;
		cout<<"字符: "<<usr[i].word<<"  "<<"权值:"<<usr[i].weight<<endl;
		i++;if(i==n)break;
		cin>>m;
	}

    FILE *fp;
    fp = fopen("user", "w+");
    if (!fp) 
    {

         printf("Open file error!\n");
         system("pause");
         return -1;
     }
     //将结构体数据写入文件
	for(int r=0;r!=n;r++){
		fwrite(&usr[r], sizeof(FreOfCh), 1, fp);
	}
	free(usr);fclose(fp);
	fp=fopen("user","r");
	usr=new FreOfCh[n];
    for(int r=0;r!=n;r++){
		fread(&usr[r], sizeof(FreOfCh), 1, fp);
	}
     rewind(fp);    //将指针移到文件头处     
	 fclose(fp);free(usr);
	 return n;
}


int CreatHufTree_sys(HuffmanTree &HT,int &n){//w存放n个字符的权值
    FILE *fp;
    fp = fopen("sys", "r");//文件sys已经在main中初始化好了
    if (!fp) 
    {

         printf("Open file error!\n");
         system("pause");
         return -1;
     }
    struct FreOfCh *syst=(FreOfCh*)malloc(28*sizeof(FreOfCh));
	syst[0].weight=0;syst[0].word=' ';
	for(int r=1;r!=28;r++){
		fread(&syst[r], sizeof(FreOfCh), 1, fp);
	}
	fclose(fp);
	int s1,s2;
	n=27;
	int m=2*n-1;int i=0;HuffmanTree p=NULL;
	HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
	for(i=1,p=HT+1;i<=n;++i,++p) {
		p->weight=syst[i].weight;
		p->parent=p->lchild=p->rchild=0;
		p->word=syst[i].word;
		p->mark=0;
	}
	for(;i<=m;++i,++p) {
		p->weight=p->parent=p->lchild=p->rchild=0;
		p->word=' ';
		p->mark=0;
	}
	for(i=n+1;i<=m;++i){
    //Select(HT,i-1,s1,s2);
		int b=0,a=0,j=0,k=0,start=0,r=0,s=0;//a<k
			for(k=1;k<=i-1;++k)//寻找第一个parent不为零的点
				if(HT[k].parent==0) {
					a=HT[k].weight;//a记录它的权值
					r=k;//r记录它的位置
					break;
				}
				if(k>i-1){cout<<"现在所有的节点都有parent";exit(0);}
				for(k=k+1;k<=i-1;k++)//寻找第二个parent不为零的点
					if(HT[k].parent==0){
						start=k;s=k;//s记录它的位置
						j=HT[k].weight;//j记录它的权值
						break;
					}
				if(a>j){b=a;a=j;j=b;b=s;s=r;r=b;}//j始终是a和j中的大值,与之相对应s始终是权值为j的点所对应的位置
				for(k=start+1;k<=n;k++){
					if(HT[k].parent!=0) continue;
					else if(HT[k].weight<j) {j=HT[k].weight;s=k;}
					if(a>j) {b=a;a=j;j=b;}
				}
				s1=r;s2=s;//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;
	}
    fp = fopen("HufTree", "wb");//文件sys已经在main中初始化好了
    if (!fp) 
    {

         printf("Open file error!\n");
         system("pause");
         return -1;
     }
	for(int r=1;r!=m+1;r++){//存入文件HufTree文件中
		fwrite(&HT[r], sizeof(HTNode), 1, fp);
	}fclose(fp);free(HT);
	return n;//n=27
	
}




void CreatHufTree_user(HuffmanTree &HT,int n){//w存放n个字符的权值
    FILE *fp;
    fp = fopen("user", "r");//文件user在ReInitFileOfHuf()中初始化好了
    if (!fp) 
    {

         printf("Open file error!\n");
         system("pause");
         return ;
     }
    struct FreOfCh *usr=(FreOfCh*)malloc((n+1)*sizeof(FreOfCh));
	for(int r=1;r!=n+1;r++){
		fread(&usr[r], sizeof(FreOfCh), 1, fp);
	}
	fclose(fp);
	//打开  
	if(n<=1)return ;
	int s1,s2;
	int m=2*n-1;int i=0;
	HuffmanTree p=NULL;
    HuffmanTree q=NULL;
	HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
	HT[0].lchild=HT[0].parent=HT[0].rchild=HT[0].weight=0;HT[0].word=' ';
	q=p=HT+1;
	for(i=1;i<=n;++i,++p) {
		p->weight=usr[i].weight;
		p->parent=p->lchild=p->rchild=0;
		p->word=usr[i].word;
	}
	for(;i<=m;++i,++p) {
		p->weight=p->parent=p->lchild=p->rchild=0;
		p->word=' ';
	}
	for(i=n+1;i<=m;++i){
	//Select(q,i-1,s1,s2);
     int b=0,a=0,j=0,k=0,start=0,r=0,s=0;//a<k
		for(k=1;k<=i-1;++k)//寻找第一个parent为零的点
			if(HT[k].parent==0) {
				a=HT[k].weight;//a记录它的权值
				r=k;//r记录它的位置
				break;
			}
			if(k>i-1){cout<<"现在所有的节点都有parent";exit(0);}
			for(k=k+1;k<=i-1;k++)//寻找第二个parent为零的点
				if(HT[k].parent==0){
					start=k;s=k;//s记录它的位置
					j=HT[k].weight;//j记录它的权值
					break;
				}
			if(a>j){b=a;a=j;j=b;b=s;s=r;r=b;}//j始终是a和j中的大值,与之相对应s始终是权值为j的点所对应的位置
			for(k=start+1;k<=i-1;k++){
				if(HT[k].parent!=0) continue;
				else if(HT[k].weight<j) {j=HT[k].weight;s=k;}
				if(a>j) {b=a;a=j;j=b;}
			}
			s1=r;s2=s;//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;
	}
    fp = fopen("HufTree", "wb");//文件sys已经在main中初始化好了
    if (!fp) 
    {
		printf("Open file error!\n");
        system("pause");
        return ;
     }
	for(int r=1;r!=m+1;r++){//存入文件HufTree文件中
	    fwrite(&HT[r], sizeof(HTNode),1,fp);
	}
	fclose(fp);free(usr);free(HT);
	return ;
	
}
//=====================一级调度函数=========================================

int menu_select(){//菜单选择函数
	int sn;
	cout<<"          哈弗曼 编码--译码 系统               "<<endl;
    cout<<"==============================================="<<endl;
	cout<<"          1. 初始化                            "<<endl;
    cout<<"          2. 编码                              "<<endl;
	cout<<"          3. 译码                              "<<endl;
	cout<<"          4. 打印代码文件                      "<<endl;
	cout<<"          5. 打印haufman树                     "<<endl;
	cout<<"          0. 退出                              "<<endl;
	cout<<"==============================================="<<endl;
	cout<<"          请选择0---5  !                      "<<endl;
	for(;;){
		//清理缓冲区
		scanf_s("%d",&sn);
		if(sn > 5 || sn < 0){
			cout<<"输入错误!请重新输入0-----5 !"<<endl;
			break;
		}
		else
			break;
	}
	return sn;
}//menu_select



void InitFileOfHuf(int &n) {//系统字符频度集合文件sys的建立
	struct FreOfCh *syst=(FreOfCh*)malloc(28*sizeof(FreOfCh));
	char word[27]  ={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',' '};
	int  weight[27]={64,13,22,32,103,21,15,47,57,1,5,32,20,57,63,15,1,48,51,80,23,8,18,1,16,1,186};
	for(int i=1;i!=28;i++){
		syst[i].word=word[i-1];
	    syst[i].weight=weight[i-1];
	}
	FILE *fp;
    fp = fopen("sys", "w");
    if (!fp) 
    {

         printf("Open file error!\n");
         system("pause");
         return ;
     }
     //将结构体数据写入文件
   for(int r=1;r!=28;r++){
     fwrite(&syst[r], sizeof(FreOfCh), 1, fp);
	}
     //从文件中读出结构体数据
     rewind(fp);    //将指针移到文件头处
	 fclose(fp);
	 free(syst);
	 n=27;
	 return;
}



void InitHufTree(HuffmanTree &HT,int &n){
	int i=0;
	cout<<"    1.重新输入字符集和频度"<<endl;
	cout<<"    2.使用已经初始化好的测试数据        "<<endl;
	for(;;){
		cin>>i;
		if(i==1){
			ReInitFileOfHuf(n);//重新初始化;
			CreatHufTree_user(HT, n);//调用建树函数
		    break;
		}
		else if(i==2){
			CreatHufTree_sys(HT,n);//调用建树函数
			break;
		}else {cout<<"   输入出错  请输入1 或 2 !"<<endl;break;}
	}
	return ;
}



void EnCoding(int n){
    /*cout<<n;*/
	
    HuffmanTree HT;
	int m=2*n-1;
	HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
	FILE *fp;
	fp = fopen("HufTree", "rb");
    if (!fp) 
    {
		printf("Open file error!\n");
        system("pause");
        return ;
     }
	for(int r=1;r!=m+1;r++){
		fread(&HT[r],sizeof(HTNode),1,fp);
	}
	fclose(fp);
	HuffmanCode HC;
	HC=(HuffmanCode)malloc((n+1)*sizeof(char*));
	char*cd=(char*)malloc(n*sizeof(char));
	cd[n-1]='\0';int start=1;int c=0, f=1;
	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));
		strcpy(HC[i],&cd[start]);
	}
	free(cd);
	//存入TotalCodeFile中
    fp = fopen("TotalCodeFile", "wb");
    if (!fp) 
    {
		printf("Open file error!\n");
        system("pause");
        return ;
     }
    codefilenode *CodeFileNode;
	CodeFileNode=(codefilenode*)malloc((n+1)*sizeof(codefilenode));
	for(int r=1;r<=n;r++){
		CodeFileNode[r].word=HT[r].word;
	    CodeFileNode[r].code=HC[r];
	}
	free(HT);free(HC);
	for(int r=1;r!=n+1;r++){
		fwrite(&CodeFileNode[r],sizeof(codefilenode),1,fp);
	}
	fclose(fp);
	//ToBeTran编译开始
	fp = fopen("AimCodeFile", "wb");
    if (!fp) 
    {
		printf("Open file error!\n");
        system("pause");
        return ;
     }
	cin.sync();
	cout<<"请输入要编码的的字符串(以#结束)"<<endl;
	char ch;
    scanf_s("%c",&ch);
	cout<<"下面是编码结果(将存入AimCodeFile中)"<<endl;
	while(ch!='#'){
		for(c=1;c<=n;c++)
			if(ch==CodeFileNode[c].word){ 
				printf("%s",CodeFileNode[c].code);
				fprintf(fp,"%s",CodeFileNode[c].code);//存入文件AimCodeFile中
				break;
			}
		ch=getchar();
	}
	cout<<endl;
	fclose(fp);
	free(CodeFileNode);
	cout<<"编码结束"<<endl;
    return;
}

		

void Decoding(int n){
	HuffmanTree HT;int m=2*n-1;
	HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
    FILE *fp = fopen("HufTree", "rb");
	if (!fp) 
    {
		printf("Open file error!\n");
        system("pause");
        return ;
     }
	for(int i=1;i<=m;i++){
		fread(&HT[i],sizeof(HTNode),1,fp);
	}
	fclose(fp);
	fp = fopen("TextFile", "wb");
    if (!fp) 
    {
		printf("Open file error!\n");
        system("pause");
        return ;
     }
   
	cout<<"请输入需要译码的码串!(以#结束)"<<endl;
	cin.sync() ;   

	char ch=getchar();
	cout<<"下面是译码结果"<<endl;
	while(ch!='#'){
		if(ch=='0'){
            m=HT[m].lchild;
			if(HT[m].lchild==0 && HT[m].rchild==0){
				cout<<HT[m].word;
				fputc(HT[m].word,fp);
				m=m=2*n-1;
			}else {
			}
		}else{ 
			m=HT[m].rchild;
			if(HT[m].rchild==0 && HT[m].lchild==0){
			       cout<<HT[m].word;
				   fputc(HT[m].word,fp);
				   m=m=2*n-1;
		        }else{
		        }
		}
		ch=getchar();
	}
	fclose(fp);
	cout<<endl<<"译码结束(存入TextFile中)"<<endl;
}//decoding()


			


void PrintfAimCodeFile(){
	FILE *fp;
	fp=fopen("AimCodeFile","rb");
	if(!fp){
		cout<<"Can't open the file";
		return;
	}
	char ch=fgetc(fp);
	int i;
	while(ch!=EOF){
	for(i=1;i!=51;i++){
		cout<<ch;
		ch=fgetc(fp);
	}
	cout<<endl;
	}
	fclose(fp);
}



void PrintHufTree(int n){
	FILE *fp;int m=2*n-1;
	fp=fopen("HufTree","rb");
	if(!fp){cout<<"Can't open it";return;}
	HuffmanTree HT,p,q;
	HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
	for(int i=1;i!=m+1;i++){
		fread(&HT[i],sizeof(HTNode),1,fp);
	}
	fclose(fp);
	p=HT+m;int r=0;
	SqStack S;
	InitStack(S);Push(S,p);
	while(S.top!=S.base){
		Pop(S,q);
		if(q==HT+p->rchild) m=m+1;                  
		for(int i=0;i!=m;i++)
			cout<<"-";
		cout<<q->word<<"  "<<q->weight<<endl;
		m--;//打印q
		if(q->rchild){
		  q=HT+q->rchild;
		  Push(S,q);
		  r=q->parent;
		  q=HT+r;
		  q=HT+q->lchild;
		  Push(S,q);
		}else m++;
	}
	return;
}

       

	

//===============================main()==================================

void main()
{
	HuffmanTree HT;
	int i=0,n=0;
	InitFileOfHuf(n);
	for(;;){
		i=menu_select();
		switch(i){
		case 1:
			cout<<" ===========  初 始 化  ============ "<<endl;
			InitHufTree(HT,n);//初始化函数
		    break;
		case 2:
			cout<<" ===========  编    码  ============ "<<endl;
			EnCoding(n);//编码函数,建立TotleCodeFile文件;利用TotleCodeFile给ToBeTran编码,存入CodeFile中
   		    break;
		case 3:
			cout<<" ===========  译    码  ============ "<<endl;
			Decoding(n);
			break;
		case 4:
			cout<<" ============  打印代码文件 ============= "<<endl;
			PrintfAimCodeFile();//打印代码文件函数
			break;
		case 5:
			cout<<" ===========  打印hufman树 =============="<<endl;
			PrintHufTree(n);//打印hufman树函数
			break;
		case 0:
			cout<<"            谢谢使用   再见!O(∩_∩)O     ============="<<endl;
			return;
		}
		
	}
}

	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -