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

📄 haffmantree.cpp

📁 哈弗曼编码
💻 CPP
字号:
#include <iostream.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
typedef struct{
	int weight;
	int lchild;
	int rchild;
}HTNode;
typedef struct{
	HTNode * HTree;
	int root;   //根结点的位置
}HuffmanTree;



int SelectMin(HuffmanTree HT,int* visit,int num){
	//在数组HT.HTree的前num个元素中选择weight最小的,返回数组序号
	//visit=1时表示不可选,=0时表示可选
	int min=0;
	while(visit[min])min++;
	for(int i=min;i<num;i++)
		if((HT.HTree[i].weight<HT.HTree[min].weight) && (visit[i]==0))   min=i; 
    visit[min]=1;
	return min;                                    
}

void CreateHuffmanTree(HuffmanTree HT,int* w,int n){
	//对N个字符建立Huffman树,w[]记录字符相应的权重
	int m,min1,min2,* visit;   HTNode* p;                   
	m=2*n-1;  visit=new int[m];   p=HT.HTree;
    for(int i=0;i<n;i++,p++){
		p->weight=w[i];   p->lchild=-1; p->rchild=-1; visit[i]=0;
	}
	for(;i<m;i++,p++){
		p->weight=0;     p->lchild=-1; p->rchild=-1; visit[i]=0;
	}
	for(i=n,p=HT.HTree+n;i<m;i++,p++){
		min1=SelectMin(HT,visit,i);
		min2=SelectMin(HT,visit,i);
		p->weight=HT.HTree[min1].weight+HT.HTree[min2].weight;
		p->lchild=min1;  p->rchild=min2;
	}
	HT.root=m-1;                                    
}

void Coding(HuffmanTree T,int i,int *codes,int code){
	if(i==-1)  return;
	if((T.HTree[i].lchild==-1) && (T.HTree[i].rchild==-1)){
		codes[i]=code; return;
	}
	
	code=code<<1; 
	Coding(T,T.HTree[i].lchild,codes,code);
	code+=1;  
	Coding(T,T.HTree[i].rchild,codes,code);
	code=code>>1; 
}

void HuffmanCoding(HuffmanTree T,int *codes){
	int code=1;     
	Coding(T,T.root,codes,code);
}

char *IntToTwice(int n){
	int num=n;
	int count=0;
	while(num/=2) count++;
	char *s=new char[count+1];
	s[count]='\0';
	num=n%int(pow(2,count));
	int j=0;
	while(j<count){
		s[count-j-1]=num%2+'0';
		num/=2;
		j++;
	}
	return s;
}

void SaveZifuCode(char *filename,char *zifu,int *codes,int n){
	FILE *fp;
	if((fp=fopen(filename,"w"))==NULL){
		cout<<"Can't open the file!"<<endl;
		exit(0);
	}
	for(int i=0;i<n;i++){
		fputc(zifu[i],fp);
		fputs("--",fp);
		fputs(IntToTwice(codes[i]),fp);
		fputc('\n',fp);
	}
}


void InorderTraverse(HuffmanTree HT,int i,int *inorder,int *j){
	if(i==-1) return;
	if((HT.HTree[i].lchild==-1) && (HT.HTree[i].rchild==-1)){
		inorder[(*j)++]=i;  return;
	}
	InorderTraverse(HT,HT.HTree[i].lchild,inorder,j);
	inorder[(*j)++]=i;
	InorderTraverse(HT,HT.HTree[i].rchild,inorder,j);
}


void InorderTraverseTree(HuffmanTree HT,int *inorder){
	int i=0;
	int *j=&i;
    InorderTraverse(HT,HT.root,inorder,j);
}

void FloorTraverse(HuffmanTree HT,int *floor){
	int front,rear,t;
	front=rear=0;
	floor[front]=HT.root;
	while(front<=rear){
		t=floor[front];
		if(HT.HTree[t].lchild!=-1)  floor[++rear]=HT.HTree[t].lchild;
	    if(HT.HTree[t].rchild!=-1)  floor[++rear]=HT.HTree[t].rchild;
		front++;
	}
}

void TreePrint(HuffmanTree HT,int m,char *zifu,char sign){
	char *allzifu=new char[m];
	int *inorder=new int[m];
	int *floor=new int[m];
	for(int i=0;i<(m+1)/2;i++)  allzifu[i]=zifu[i];
	while(i<m){ 
		allzifu[i]=sign;  i++;
	}
	InorderTraverseTree(HT,inorder);
	FloorTraverse(HT,floor);
	i=0; int k,t;
	cout<<"HuffmanTree is as followed:"<<endl;
	while(i<m){
		k=0;
		for(int j=0;j<m;j++){
			if(floor[i]==inorder[j]){
				for(t=k;t<j;t++) cout<<' ';
				cout<<allzifu[floor[i]];
				k=j+1; i++;
			}
		}
		cout<<endl;
	}
}

void InputTextFile(char *filename){
	FILE *fp;
    if((fp=fopen(filename,"w"))==NULL){
		cout<<"Can't open the file!"<<endl;
		exit(0);
	}
	char c;
	cout<<"Please input the text:"<<endl;
	while((c=getchar())!='#')fputc(c,fp);
	fputc('#',fp);
	fclose(fp);
}

void TransTextToCode(char *textfile,char *codefile,int *codes,char *zifu){
    FILE *fp1,*fp2;
    if((fp1=fopen(textfile,"r"))==NULL){
		cout<<"Can't open the file!"<<endl;
		exit(0);
	}
    if((fp2=fopen(codefile,"w"))==NULL){
		cout<<"Can't open the file!"<<endl;
		exit(0);
	}
	int j;char c=fgetc(fp1);
	while(c!='#'){
		 j=0;
	    while(zifu[j]!=c) j++;
	    fputs(IntToTwice(codes[j]),fp2);
		c=fgetc(fp1); 
	}
	fputc('#',fp2);
    fclose(fp1);  fclose(fp2);
}

void CodePrint(char *codefile,char *stdcodefile){
	//把编码文件转化为每行50个的标准编码文件
    FILE *fp1,*fp2;
    if((fp1=fopen(codefile,"r"))==NULL){
		cout<<"Can't open the file!"<<endl;
		exit(0);
	}
    if((fp2=fopen(stdcodefile,"w"))==NULL){
		cout<<"Can't open the file!"<<endl;
		exit(0);
	}
	char c=fgetc(fp1);
    int i;
	cout<<"The codes are:"<<endl;
	while(c!='#'){
		i=0;
	    while(i<50 && c!='#'){
            fputc(c,fp2); i++; cout<<c;c=fgetc(fp1);
		}
		fputc('\n',fp2); cout<<endl;
	}
    fclose(fp1);fclose(fp2);
}

int Match(int m,int *codes,int n){
	//匹配编码与字符,成功返回字符序号,反之返回-1
	for(int i=0;i<n;i++)
		if(m==codes[i]) return i;
    return -1;
}

void TransCodeToText(char *codefile,char *textfile,int *codes,int n,char *zifu){
    FILE *fp1,*fp2;
    if((fp1=fopen(codefile,"r"))==NULL){
		cout<<"Can't open the file!"<<endl;
		exit(0);
	}
    if((fp2=fopen(textfile,"w"))==NULL){
		cout<<"Can't open the file!"<<endl;
		exit(0);
	}
    char c=fgetc(fp1);  int num=1; int i;
	while(c!='#'){
		num=2*num+(c-'0');
		if((i=Match(num,codes,n))!=-1){
			fputc(zifu[i],fp2); num=1;
		}
		c=fgetc(fp1);
	}
	fputc('#',fp2);
	fclose(fp1); fclose(fp2);
}






void main(){
	int n,* w,*codes; HuffmanTree HT; char * zifu;
	cout<<"Please input the number of chars:"<<endl;
	cin>>n;     
	codes=new int[n];
	w=new int[n];
	zifu=new char[n];
    HT.root=2*n-2;
    HT.HTree=new HTNode[2*n-1];
	cout<<"Please input chars:"<<endl;
    for(int i=0;i<n;i++) cin>>zifu[i];
	cout<<"Please input the weights of chars:"<<endl;
	for(i=0;i<n;i++) cin>>w[i];


	CreateHuffmanTree(HT,w,n);
    
    HuffmanCoding(HT,codes);

    SaveZifuCode("HfmTree.txt",zifu,codes,n);

    TreePrint(HT,2*n-1,zifu,'*');

	InputTextFile("ToBeTrans.txt");
	
	TransTextToCode("ToBeTrans.txt","CodeFile.txt",codes,zifu);
	
	CodePrint("CodeFile.txt","CodePrin.txt");
    
	TransCodeToText("CodeFile.txt","TextFile.txt",codes,n,zifu);
}


⌨️ 快捷键说明

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