一个cpp文件
#include<iostream>
#include<cstdio>
#include<fstream>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
const int MAX = 256;
#define LL long long
struct HTNode {
unsigned char data;
int weight;
int parent, lchild, rchild;
HTNode() {
weight = parent = lchild = rchild = -1;
}
};
LL inputlen;
int n = 0;
HTNode *arr;
map<char, vector<int>> mp;
unsigned char* char_huffman;
LL openfile(char* name);
void Count(LL filelen);
void CreateHuffmanTree();
void HaffmanCode();
void outPutTree();
void Binarycode();
int Translate();
unsigned char int_to_char(int *a);
void char_to_int(int x, int* a);
int main() {
cout<<"请输入要压缩的文件名字"<<endl;
char filename[MAX];
cin.getline(filename,MAX);
arr = new HTNode[2*MAX - 1];
inputlen = openfile(filename);
Count(inputlen);
CreateHuffmanTree();
HaffmanCode();
outPutTree();
Binarycode();
int outputlen = Translate();
double rate = (double)outputlen/inputlen;
printf("\n");
printf("文件压缩成功,压缩比为:%lf",rate);
return 0;
}
LL openfile(char* name){
FILE* file1 = NULL;
file1 = fopen(name,"rb");
if(file1 == NULL){
cout<<"打开文件失败!"<<endl;
exit(1);
}
cout<<"input.txt文件打开成功!"<<endl;
cout<<endl;
fseek(file1,0,SEEK_END);
LL filelen = ftell(file1);
rewind(file1);
char_huffman = new unsigned char[filelen];
for(LL i=0;i<filelen;i++){
char_huffman[i] = 0;
}
fread(char_huffman,1,filelen,file1);
fclose(file1);
return filelen;
}
void Count(LL filelen){
for (LL i = 0; i < filelen; i++) {
int flag = 0;
for (int j = 0; j < n; j++) {
if (arr[j].data == char_huffman[i]) {
flag = 1;
arr[j].weight++;
break;
}
}
if (!flag) {
arr[n].data = char_huffman[i];
arr[n].weight = 1;
n++;
}
}
}
void CreateHuffmanTree() {
for (int i = n; i < 2 * n - 1; i++) {
LL min1 = 10000000; LL min2 = min1;
int x1 = -1, x2 = -1;
for (int j = 0; j < i; j++) {
if (arr[j].parent == -1) {
if (arr[j].weight < min1) {
min2 = min1;
x2 = x1;
min1 = arr[j].weight;
x1 = j;
}
else if (arr[j].weight < min2) {
min2 = arr[j].weight;
x2 = j;
}
}
}
arr[x1].parent = arr[x2].parent = i;
arr[i].weight = min1 + min2;
arr[i].lchild = x1;
arr[i].rchild = x2;
}
}
void HaffmanCode()
{
for (int i = 0; i < n; i++) {
int t = i;
vector<int> v;
int parent = arr[i].parent;
for (int j = parent; j != -1; t = j, j = arr[j].parent) {
if (arr[j].lchild == t) {
v.push_back(0);
}
else {
v.push_back(1);
}
}
reverse(v.begin(),v.end());
mp[arr[i].data]= v;
}
}
void outPutTree(){
cout<<"字符对应的编码为:"<<endl;
for(map<char,vector<int>>::iterator it = mp.begin();it != mp.end();it++){
printf("%c ",it->first);
for(int i=0;i<(*it).second.size();i++){
printf("%d",(*it).second[i]);
}
printf("\n");
}
printf("输出哈夫曼树:\n");
printf("下标\t权值\t父结点\t左孩子\t右孩子\t结点\n");
for(int i=0;i<2*n-1;i++){
printf("%d\t%d\t%d\t%d\t%d\t%c\t\n",i,arr[i].weight,arr[i].parent,arr[i].lchild,arr[i].rchild,arr[i].data);
}
printf("\n");
}
void Binarycode(){
ofstream file1("output.txt");
if(!file1.is_open()){
printf("output.txt文件打开失败\n");
exit(1);
}
printf("压缩编码时,output.txt文件打开成功!\n");
printf("\n");
int buffer[8] = {0};
int count = 0;
for(int i=0;i<inputlen;i++){
int x;
x = char_huffman[i];
for(int j=0;j<mp[x].size();j++){
if(count == 8){
file1<<int_to_char(buffer);
count = 0;
}
buffer[count] = mp[x][j];
count++;
}
}
if(count != 0){
file1<<int_to_char(buffer);
}
char lackcount = count;
file1<<lackcount;
file1.close();
}
int Translate(){
FILE* file1 = NULL;
file1 = fopen("output.txt","rb");
if(file1 == NULL){
cout<<"写入文件时,文件output.txt打开失败!"<<endl;
exit(1);
}
cout<<"译码时,output.txt文件打开成功!"<<endl;
cout<<endl;
fseek(file1,0,SEEK_END);
LL filelen = ftell(file1);
rewind(file1);
unsigned char* buf = new unsigned char[filelen];
for(int i=0;i<filelen;i++){
buf[i] = 0;
}
fread(buf,1,filelen,file1);
fclose(file1);
vector<int> source;
int a[8];
for(int i=0;i<8;i++){
a[i] = 0;
}
for(int i=0;i<filelen - 2;i++){
char_to_int(buf[i],a);
for(int j = 0 ;j<8;j++){
source.push_back(a[j]);
}
}
int lackcount = buf[filelen - 1];
char_to_int(buf[filelen - 2],a);
for(int j=0;j<lackcount;j++){
source.push_back(a[j]);
}
ofstream file2("original.txt",ios::binary);
if(!file2.is_open()){
printf("文件original.txt打开失败!");
exit(1);
}
printf("译码时,original.txt文件打开成功!");
printf("\n");
int q = 2 * n - 2;
for (int i = 0;i<source.size();i++){
if (source[i] == 0) {
q = arr[q].lchild;
}
else if (source[i] == 1) {
q = arr[q].rchild;
}
if (arr[q].lchild == -1 && arr[q].rchild == -1) {
if(arr[q].data != 13)
file2<<arr[q].data;
q = 2 * n - 2;
}
}
return filelen;
}
unsigned char int_to_char(int *a){
unsigned char x;
x = a[0]*128 + a[1]*64 + a[2]*32 + a[3]*16 + a[4]*8 + a[5]*4 + a[6]*2 + a[7]*1;
return x;
}
void char_to_int(int x, int* a){
for(int i=7;i>=0;i--){
a[i] = x % 2;
x = x / 2;
}
}
拆分后有多个头文件和源文件
HTNode.h
#ifndef HTNode_H
#define HTNode_H
struct HTNode {
unsigned char data;
int weight;
int parent, lchild, rchild;
HTNode() {
weight = parent = lchild = rchild = -1;
}
};
#endif
variable.h
#ifndef VARIABLE_H
#define VARIABLE_H
#include"HTNode.h"
#include<iostream>
#include<map>
#include <vector>
#include<cstdio>
#include<fstream>
#include<algorithm>
using namespace std;
#define LL long long
const int MAX = 256;
LL inputlen;
int n = 0;
HTNode *arr;
map<char,vector<int>> mp;
unsigned char* char_huffman;
#endif
function.h
#ifndef FUNCTION_H
#define FUNCTION_H
#include"variable.h"
unsigned char int_to_char(int *a);
void char_to_int(int x, int* a);
#endif
function.cpp
#include"function.h"
unsigned char int_to_char(int *a){
unsigned char x;
x = a[0]*128 + a[1]*64 + a[2]*32 + a[3]*16 + a[4]*8 + a[5]*4 + a[6]*2 + a[7]*1;
return x;
}
void char_to_int(int x, int* a){
for(int i=7;i>=0;i--){
a[i] = x % 2;
x = x / 2;
}
}
openandcount.h
#ifndef OAC_H
#define OAC_H
#include"variable.h"
LL openfile(char* name);
void Count(LL filelen);
#endif
openandcount.cpp
#include"openandcount.h"
LL openfile(char* name){
FILE* file1 = NULL;
file1 = fopen(name,"rb");
if(file1 == NULL){
cout<<"打开文件失败!"<<endl;
exit(1);
}
cout<<"input.txt文件打开成功!"<<endl;
cout<<endl;
fseek(file1,0,SEEK_END);
LL filelen = ftell(file1);
rewind(file1);
char_huffman = new unsigned char[filelen];
for(LL i=0;i<filelen;i++){
char_huffman[i] = 0;
}
fread(char_huffman,1,filelen,file1);
fclose(file1);
return filelen;
}
void Count(LL filelen){
for (LL i = 0; i < filelen; i++) {
int flag = 0;
for (int j = 0; j < n; j++) {
if (arr[j].data == char_huffman[i]) {
flag = 1;
arr[j].weight++;
break;
}
}
if (!flag) {
arr[n].data = char_huffman[i];
arr[n].weight = 1;
n++;
}
}
}
huffman.h
#ifndef HUFFMAN_H
#define HUFFMAN_H
#include"variable.h"
void CreateHuffmanTree();
void HaffmanCode();
void outPutTree();
#endif
huffman.cpp
#include"huffman.h"
void CreateHuffmanTree() {
for (int i = n; i < 2 * n - 1; i++) {
LL min1 = 10000000; LL min2 = min1;
int x1 = -1, x2 = -1;
for (int j = 0; j < i; j++) {
if (arr[j].parent == -1) {
if (arr[j].weight < min1) {
min2 = min1;
x2 = x1;
min1 = arr[j].weight;
x1 = j;
}
else if (arr[j].weight < min2) {
min2 = arr[j].weight;
x2 = j;
}
}
}
arr[x1].parent = arr[x2].parent = i;
arr[i].weight = min1 + min2;
arr[i].lchild = x1;
arr[i].rchild = x2;
}
}
void HaffmanCode() {
for (int i = 0; i < n; i++) {
int t = i;
vector<int> v;
int parent = arr[i].parent;
for (int j = parent; j != -1; t = j, j = arr[j].parent) {
if (arr[j].lchild == t) {
v.push_back(0);
}
else {
v.push_back(1);
}
}
reverse(v.begin(),v.end());
mp[arr[i].data]= v;
}
}
void outPutTree(){
cout<<"字符对应的编码为:"<<endl;
for(map<char,vector<int>>::iterator it = mp.begin();it != mp.end();it++){
printf("%c ",it->first);
for(int i=0;i<(*it).second.size();i++){
printf("%d",(*it).second[i]);
}
printf("\n");
}
printf("输出哈夫曼树:\n");
printf("下标\t权值\t父结点\t左孩子\t右孩子\t结点\n");
for(int i=0;i<2*n-1;i++){
printf("%d\t%d\t%d\t%d\t%d\t%c\t\n",i,arr[i].weight,arr[i].parent,arr[i].lchild,arr[i].rchild,arr[i].data);
}
printf("\n");
}
binarycode.h
#ifndef BINARYCODE_H
#define BINARYCODE_H
#include"variable.h"
#include"function.h"
void Binarycode();
#endif
binarycode.cpp
#include"binarycode.h"
void Binarycode(){
ofstream file1("output.txt");
if(!file1.is_open()){
printf("output.txt文件打开失败\n");
exit(1);
}
printf("压缩编码时,output.txt文件打开成功!\n");
printf("\n");
int buffer[8] = {0};
int count = 0;
for(int i=0;i<inputlen;i++){
int x;
x = char_huffman[i];
for(int j=0;j<mp[x].size();j++){
if(count == 8){
file1<<int_to_char(buffer);
count = 0;
}
buffer[count] = mp[x][j];
count++;
}
}
if(count != 0){
file1<<int_to_char(buffer);
}
char lackcount = count;
file1<<lackcount;
file1.close();
translate.h
#ifndef TRANSLATE_H
#define TRANSLATE_H
#include"variable.h"
#include"function.h"
int Translate();
#endif
translate.cpp
#include"translate.h"
int Translate(){
FILE* file1 = NULL;
file1 = fopen("output.txt","rb");
if(file1 == NULL){
cout<<"写入文件时,文件output.txt打开失败!"<<endl;
exit(1);
}
cout<<"译码时,output.txt文件打开成功!"<<endl;
cout<<endl;
fseek(file1,0,SEEK_END);
LL filelen = ftell(file1);
rewind(file1);
unsigned char* buf = new unsigned char[filelen];
for(int i=0;i<filelen;i++){
buf[i] = 0;
}
fread(buf,1,filelen,file1);
fclose(file1);
vector<int> source;
int a[8];
for(int i=0;i<8;i++){
a[i] = 0;
}
for(int i=0;i<filelen - 2;i++){
char_to_int(buf[i],a);
for(int j = 0 ;j<8;j++){
source.push_back(a[j]);
}
}
int lackcount = buf[filelen - 1];
char_to_int(buf[filelen - 2],a);
for(int j=0;j<lackcount;j++){
source.push_back(a[j]);
}
ofstream file2("original.txt",ios::binary);
if(!file2.is_open()){
printf("文件original.txt打开失败!");
exit(1);
}
printf("译码时,original.txt文件打开成功!");
printf("\n");
int q = 2 * n - 2;
for (int i = 0;i<source.size();i++){
if (source[i] == 0) {
q = arr[q].lchild;
}
else if (source[i] == 1) {
q = arr[q].rchild;
}
if (arr[q].lchild == -1 && arr[q].rchild == -1) {
if(arr[q].data != 13)
file2<<arr[q].data;
q = 2 * n - 2;
}
}
return filelen;
}
main.cpp
#include"variable.h"
#include"function.h"
#include"openandcount.h"
#include"huffman.h"
#include"binarycode.h"
#include"translate.h"
#include"function.cpp"
#include"openandcount.cpp"
#include"huffman.cpp"
#include"binarycode.cpp"
#include"translate.cpp"
int main() {
cout<<"请输入要压缩的文件名字"<<endl;
char filename[MAX];
cin.getline(filename,MAX);
arr = new HTNode[2*MAX - 1];
inputlen = openfile(filename);
Count(inputlen);
CreateHuffmanTree();
HaffmanCode();
outPutTree();
Binarycode();
int outputlen = Translate();
double rate = (double)outputlen/inputlen;
printf("\n");
printf("文件压缩成功,压缩比为:%lf",rate);
return 0;
}