zoukankan      html  css  js  c++  java
  • 哈夫曼树应用——压缩文件大小

    #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] = '';
    			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] != ''){
    				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] != ''){
    				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] != '' ; 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] = ''; 
    		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
    ",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] != ''){
    			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
    ",arr[i]);
    		}
    		memset(arr,0,20);
    		printf("
    ");
    		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;
    }
    
  • 相关阅读:
    SpringBoot 项目瘦身
    对比两个文本的异同
    Spring 事务不起作用的场景
    Controller 层数据校验实现思路
    Notify 类的实现思路
    backup: 使用 vim 时一定会用到的设置 --for-myself
    exercise: 反射获取指定的属性值 --CSharp
    exercise: 序列化和反序列化Xml --CSharp
    前缀
    华罗庚的数学思想
  • 原文地址:https://www.cnblogs.com/FCY-LearningNotes/p/13810781.html
Copyright © 2011-2022 走看看