哈夫曼树应用——压缩文件大小

#include<stdio.h>
#include<stdlib.h>
#include <iostream>
#include<math.h>
#include<string.h>
using namespace std;

/* run this program using the console pauser or add your own getch, system("pause") or input loop */
struct Item{
	char value;
	int count;
	Item * next;
	Item * parent;
	Item * left;
	Item * right;
	char  code[30];
};

Item * sort(Item * res){
//	cout<<"排序开始"<<endl;
	for(Item * i = res -> next;i != NULL;i = i -> next){
		for(Item * j = i;j -> next != NULL; j = j -> next){
			if(i -> count > j -> next -> count){
				swap(i -> count,j -> next -> count);
				swap(i -> value,j -> next -> value);
				Item *p = i -> parent,*l = i -> left,*r = i -> right;
				i -> parent = j -> next -> parent;
				i -> left = j -> next -> left;
				i -> right = j -> next -> right; 
				j -> next ->parent = p;
				j -> next ->left = l;
				j -> next ->right = r;
				for(int ii = 0;ii < 30;ii++)
				swap(i -> code[ii],j -> next -> code[ii]);
			}
		}
	}
//	cout<<"排序结束"<<endl;
	return res;
}

Item * readFromFile(char * path){
//	cout<<"readFromFile"<<endl;
	int a [256]  ={0};
	char c;
	Item * head =(Item*)malloc (sizeof(Item));
	Item * aa = head;
	FILE * file = fopen(path,"r");
	while((c=fgetc(file)) != -1){
		a[c]++;
	}
	for(int i = 0;i <= 255;i++){
		if(a[i] != 0){
			head -> next = (Item*)malloc (sizeof(Item));
			head -> next -> next = NULL;
			head -> next -> value = i;
			for(int j = 0 ; j < 30 ; j++)
			head -> next -> code[j] = '\0';
			head -> next -> parent = NULL;
			head -> next -> left = NULL;
			head -> next -> right = NULL;
			head -> next -> count = a[i];
			head = head -> next;
		}
	}

	fclose(file);
	return sort(aa);
}
void setDecode(Item * item){
//	cout<<"setDecode"<<endl;
	if(item -> left != NULL){
		int i = 0;
		for(;i<30;i++){
			if(item -> code[i] != '\0'){
				item -> left -> code[i] = item -> code[i];
			}else{
				item -> left -> code[i] = '0';
				break;
			}
		} 
		setDecode(item -> left);
	}
	if(item -> right != NULL){
		int j = 0;
		for(;j<30;j++){
			if(item -> code[j] != '\0'){
				item -> right -> code[j] = item -> code[j];
			}else{
				item -> right -> code[j] = '1';
			 	break;
				}
		}
		setDecode(item -> right);			
	}
} 
void printTree(Item * item,FILE * f,char c){
	if(c == item -> value){
		for(int i = 0 ; item -> code[i] != '\0' ; i++){
			fprintf(f,"%c",item -> code[i]);	
		}
}

	if(item -> left != NULL){
		printTree( item -> left,f,c);
	}
	if(item -> right != NULL){
		printTree(item -> right,f,c);
	}
}
// 返回树的根节点 
Item * getTrees(char * src){
	Item * res = readFromFile(src);
	Item * var = res -> next;
	int i =0; 
	while(var -> next != NULL){
		i++;
		Item * a = (Item*)malloc(sizeof(Item));
		a -> left = var;
		for(int ii=0;ii<30;ii++)
		a -> code[ii] = '\0'; 
		a -> right = var -> next;
		a -> parent = NULL;
		a -> count = var -> count + var -> next -> count;
		var -> parent = a;
		var -> next -> parent = a;
		a -> value = -1;
		res -> next = a;
		a -> next = var -> next -> next;
		var = sort(res) -> next;
	}
	var -> right -> code[0] = '1';
	var -> left -> code[0] = '0';  
	setDecode(var -> right);
	setDecode(var -> left);
	return var;
}



// 将文本编码输出到文件 
int writeToFile(char * src,char * des){
	cout<<"writeToFile"<<endl;
	FILE * desF = fopen(des,"wb");
	FILE * srcF = fopen(src,"r");
	Item * tree = getTrees(src);
	char s;
	int count = 0 ;
	while((s = fgetc(srcF)) != EOF){
		count++;
		printTree(tree,desF,s);
	}
	fclose(desF);
	fclose(srcF);
	return count;
}
// 读取txt文件中的2进制字符按照二进制写入特定文件 
void printBitToFile(char * srcP,char * outBits){
	cout<<"printBitToFile"<<endl; 
	FILE * src = fopen(srcP,"r");
	FILE * des = fopen(outBits,"wb");
	char a = 0,i = 0;
	int k = 0;
	char c ;
	int yy = 0;
	int vvv = 0;
	while((c = fgetc(src)) != EOF){
		if(i == 7){
			int flag = 0;
			a = a | flag;
			i++;
		} 
		if(i == 8){
			// 将int写入文件并将i重置为0 
			fputc(a,des);
			
			if(yy <= 30){
				printf("%d\n",a);
				for(int i = 0 ; i< 8 ;i++)
				printf("%d",(a >> i ) & 1); 
				cout<<endl;
				yy++;
			}
			i = 0;
			a = 0;
		}
		if( i < 7){
			int flag;
			if(c == '1')
			flag = pow(2,i);
			else flag = 0;
						
			a = a | flag;
			i++;
			k++;
		}
	}
	
	if(i != 0){
		fprintf(des,"%c",a);
		i = 0;
		a = 0;
	}
	
	fclose(src);
	fclose(des);
	
}

//读取比特流构造原文件
void getPrimary(char* bit,char * des,int sum){
	FILE* srcF = fopen(bit,"rb");
	FILE* desF = fopen(des,"w");
	unsigned int x = 0;
	int cur = 0;
	int var;
	char c;
	Item * node = getTrees("C:\\Users\\樊晨阳1\\Desktop\\Solitude.txt");
	Item * root = node;
	c = fgetc(srcF);
	while(feof(srcF) == 0){
		for(int i = 0; i < 7 ; i++){
			var = (c >> i) & 1;			
			if(var == 1){
				node = node -> right;
			}else if(var == 0){
				node = node -> left;
			}
			
			if(node -> value != -1){
				fprintf(desF,"%c",node -> value);
				node = root;
				cur++;
				if(cur == sum)
				break;		
			}
		}
		if(cur == sum)
		break;
		c = fgetc(srcF);
	}
	printf("%d",cur);
	fclose(srcF);
	fclose(desF);
} 


//调试数据 
void show(Item * i){

	if(i -> value != -1){
		cout<<"开始"<<endl;
		cout<<"value="<<i -> value<<endl; 
		int j = 0;																	
		while(i -> code[j] != '\0'){
			printf("%c ",i -> code[j++]);
		}
		cout<<endl;
	}
	if(i -> left != NULL){
		show(i -> left);
		show(i -> right);
	}
} 
// 调试数据 
void printBIT(){
	FILE * ff = fopen("C:\\Users\\樊晨阳1\\Desktop\\out.txt","r");
	FILE * f = fopen("C:\\Users\\樊晨阳1\\Desktop\\outBit.txt","rb");
	char c ;
	char arr[20] = {0};
	int i = 0;
	while(i < 20){
		fread(arr,1,sizeof(arr)-1,f);
		for(int i =0; i< 20 ;i ++){
			printf("%d\n",arr[i]);
		}
		memset(arr,0,20);
		printf("\n");
		i++;
	}
	fclose(ff);
	fclose(f);
}
//724362
//724247
int main(int argc, char *argv[]) {
	int sum = writeToFile("C:\\Users\\樊晨阳1\\Desktop\\Solitude.txt","C:\\Users\\樊晨阳1\\Desktop\\out.txt");
	cout<<"sum = "<<sum<<endl;
	printBitToFile("C:\\Users\\樊晨阳1\\Desktop\\out.txt","C:\\Users\\樊晨阳1\\Desktop\\outBit.txt");
	show(getTrees("C:\\Users\\樊晨阳1\\Desktop\\Solitude.txt"));
	getPrimary("C:\\Users\\樊晨阳1\\Desktop\\outBit.txt","C:\\Users\\樊晨阳1\\Desktop\\primary.txt",sum);
//	printBIT();
	return 0;
}
posted @ 2020-10-13 19:51  沙雕货  阅读(47)  评论(0编辑  收藏  举报