哈夫曼编码 将文本保留在文件中自动编码

功能

Txt.txt 需要自己建立(保存英文文本)并放在和.cpp文件同个文件夹,都放在在桌面也可以。

1、 可以读取所有英文字符

2、自动计算文本中所有字符的 编码 和 权重 (字符在文件中出现次数) 保存在HuffmanCode.txt文件中

3、能将文本按照编码加密并将得到的加密文本 TxtToHu.txt,并用哈夫曼树再翻译为文本 HuToTxt.txt

4、除了Txt.txt文件需要自己建立,其他文件程序自动建立

完整代码

#include <iostream>
#include <stdlib.h>
#include <fstream>
#include <string>

using namespace std;

int NumOfChar;//字符种类 
int MaxSize; //静态链表实际使用大小 MAxsize-1也是哈夫曼树根结点的下标
const int MaxLen = 257;//256+1
typedef int Int;

typedef struct Node{
    
    
    int weight;//字符对应权重
    char c;//字符类型
    Int parent,lchild,rchild;//双亲指针,左右孩子指针
}HTNode;
HTNode Hu[MaxLen*2];//哈夫曼树结点数为2*n-1 

typedef struct HuCode{
    
    
    string code;
}HNode;

HNode HfCode[MaxLen];//用来存储哈夫曼编码
int Caculate[MaxLen];

void Get_CharInfo(void){
    
    //从文件中计算字符种类和权值 

	ifstream in;
	in.open("Txt.txt");
	
	char c;
	while(in.get(c)){
    
    //不到达文件末尾的情况下读取字符 
		Caculate[c] ++;//将读到的字符对应权重+1 
	}
	
	NumOfChar = 0;
	for(int i = 0;i < MaxLen;i++)
		if(Caculate[i]){
    
    //如果权重不为0 
			Hu[++NumOfChar].c = i;//存字符
			Hu[NumOfChar].weight = Caculate[i]; //存权重 
		}
	MaxSize = NumOfChar*2-1;//得到实际的哈夫曼树结点数量 
	in.close();//关闭文件 
	return;
}

void Creat_HuffmanTree(void){
    
    //建立哈夫曼树 
    int low1 = 0,low2 = 0;
    int indexofParent = NumOfChar+1;//第一个双亲结点下标 
   
    
    while(1){
    
    //找到权重最低的两个结点 

        low1 = low2 = 0;

        for(int i = 1;i < indexofParent;i++){
    
    //找low1
	        if(!low1 && !Hu[i].parent){
    
    //还没找到
	            low1 = i;
	        }else if(low1 && !Hu[i].parent && Hu[low1].weight > Hu[i].weight){
    
    
	            low1 = i;
	        }
    	}

	    for(int i = 1;i < indexofParent;i++){
    
    
	        if(i!=low1){
    
    
	            if(!low2 && !Hu[i].parent){
    
    //找low2
	                low2 = i;
	            }else if(low2 && !Hu[i].parent && Hu[low2].weight > Hu[i].weight){
    
    
	                low2 = i;
	            }
	        } 
	    }
	    
	    Hu[indexofParent].weight = Hu[low1].weight + Hu[low2].weight;//计算双亲结点的权重值 
	    Hu[indexofParent].lchild = low1;
	    Hu[indexofParent].rchild = low2;
	    Hu[low1].parent = indexofParent;
	    Hu[low2].parent = indexofParent;//low2为0 ???? 时indexofParent = 8指针越界 
	    
	    if(indexofParent == MaxSize){
    
    //如果哈夫曼树已经构建完成就退出  
	    	break; //已经构建 MaxSize个结点 
		}
	       
	    indexofParent++;//下个父节点位置 
	
	    }
	    
	return;
}

void Create_Huffman_Code(int index,string scode){
    
    //通过哈夫曼树建立哈夫曼编码 
		
        //index 初始值为根结点 
        if(Hu[index].lchild){
    
     //说明该结点不是叶子结点
            scode.append("0");
            Create_Huffman_Code(Hu[index].lchild,scode);

            scode = scode.substr(0,scode.length()-1);//删除末尾元素 向右子树搜索
            scode.append("1");
            Create_Huffman_Code(Hu[index].rchild,scode);
        }
        else    HfCode[(int)(Hu[index].c)].code = scode;//否则该字符完成编码
    return;
}

void Print_HuffmanCodeToFile(void){
    
    //将 字符 权重 编码 输入到文件中 
	ofstream in;
	in.open("HuffmanCode.txt");
	for(int i = 1;i <= NumOfChar;i++){
    
    
		in << "字符:" << Hu[i].c << " 权重:" << Hu[i].weight << " 编码:" <<HfCode[Hu[i].c].code<<endl;
	}
	in.close();
	return;
}

void Txt_To_Huffmantxt(void){
    
    //文本转哈夫曼编码 

    
    ifstream in;
	in.open("Txt.txt");
    
    ofstream out;
	out.open("TxtToHu.txt");
   
    char c;
   
    while(in.get(c)){
    
    
        out << HfCode[(int)c].code;
    }
    
    in.close();
    out.close();
    return;
}

void HuffmantxtToTxt(void){
    
    //哈夫曼编码转文本 
	
    ifstream in;
	in.open("TxtToHu.txt");
   
    ofstream out;
	out.open("HuToTxt.txt");
    
    char c;
    int index = MaxSize;
    
    while(in.get(c)){
    
     
    	
        if(c == '1'){
    
    //1
            if(Hu[Hu[index].rchild].rchild){
    
    //如果指向的结点不是叶子结点 
                index = Hu[index].rchild;//通过该结点是否有孩子来判断 
            }else{
    
    //是叶子结点 
                out << Hu[Hu[index].rchild].c;
                index = MaxSize;//回到根结点
            }
        }else{
    
    //0
            if(Hu[Hu[index].lchild].lchild){
    
    
                index = Hu[index].lchild;
            }else{
    
    
                out << Hu[Hu[index].lchild].c;
                index = MaxSize;
            }
        }
		
    }
    in.close();
    out.close();
    return;
}

int main(){
    
    
	
    
    string scode = "";//string 赋空 
	Get_CharInfo();//获取字符和权值 
    Creat_HuffmanTree();//建立哈夫曼树
   
    Create_Huffman_Code(MaxSize,scode);//建立哈夫曼编码
    
   	Print_HuffmanCodeToFile(); //将设计的编码输出到文件中 
    
    Txt_To_Huffmantxt();//通过查找字符对应的编码 将文本转换为编码文件
    
    HuffmantxtToTxt();//通过哈夫曼树 将编码文件转换为文本。
  
   //system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/RunningBeef/article/details/111668605