zoukankan      html  css  js  c++  java
  • 【软件开发综合实验】文本压缩软件

    使用哈夫曼编码对文本文件进行压缩。

    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<string>
    #include<queue>
    #include<map>
    #include<conio.h>
    #include<windows.h>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    typedef unsigned char uc;
    typedef unsigned long long ull;
    string s2;
    vector<int>G[512];//用vector存储哈夫曼树
    typedef vector<int>::iterator ITER;
    string anss[256];
    typedef pair<int,int> data;//堆中存储的数据类型为pair<int,int>
    #define N 1000000
    uc sp[N+5];
    int lenp;
    char s[N+5],table[256];
    int n,m;
    int cnts[256];//记录各字符出现频率
    int ReadIn(FILE* fp);//读入文本文件,返回其总长度
    void Freq_stats();//统计各字符出现频率
    void dfs(int U,string s);//深度优先遍历哈夫曼树,生成每个字符的哈夫曼编码
    void HuffmanCoding();//用堆实现哈夫曼编码主过程
    int main(){
        int op;
        char ch;
        while(1){
            system("cls");
            printf("请输入对应数字选择您想要的功能:
    ");
            printf("1.压缩当前目录下的test.txt文件到test.comp,并且输出各字符出现频率以及编码表。
    ");
            printf("2.解压当前目录下的test.comp文件,并且输出原文本到test2.txt。
    ");
            printf("3.退出程序。
    ");
            scanf("%d",&op);
            if(op==1){
                FILE* fp=fopen("test.txt","r");
                n=ReadIn(fp);
                puts("");
                fclose(fp);
                Freq_stats();
                puts("");
                HuffmanCoding();
                puts("");
                fp=fopen("test.comp","wb");
                s2.clear();
                for(int i=0;i<n;++i){
                    s2+=anss[s[i]];
                }
                cout<<"以二进制形式查看该压缩后的文件:"<<"
    "<<s2<<"
    
    ";
                lenp=0;
                int tmp=0;
                for(int i=0;i<s2.length();++i){
                    tmp=tmp*2+s2[i]-'0';
                    if(i%8==7 || i==s2.length()-1){
                        sp[lenp++]=tmp;
                        tmp=0;
                        if(i==s2.length()-1){
                            sp[lenp++]=(i+1)%8;
                            if(!sp[lenp-1]){
                                sp[lenp-1]=8;
                            }
                        }
                    }
                }
                uc t[1];
                t[0]=m;
                fwrite(t,sizeof(uc),1,fp);
                for(int i=0;i<m;++i){
                    fwrite(table+i,sizeof(char),1,fp);
                    ull tt[1]={0};
                    for(int j=0;j<anss[table[i]].length();++j){
                        tt[0]=tt[0]*2+anss[table[i]][j]-'0';
                    }
                    char tmp_len[1]; tmp_len[0]=anss[table[i]].length();
                    fwrite(tmp_len,sizeof(char),1,fp);
                    fwrite(tt,sizeof(ull),1,fp);
                }
                fwrite(sp,sizeof(uc),lenp,fp);
                fclose(fp);
                printf("按任意键继续");
                while(!kbhit());
                ch=getch();
                if(ch==-32){
                    getch();
                }
            }
            else if(op==2){
                FILE* fp=fopen("test.comp","rb");
                char M[1];
                fread(M,sizeof(char),1,fp);
                m=M[0];
                memset(cnts,0,sizeof(cnts));
                ull anss[256]={0};
                char x[1];
                ull y[1];
                char tlen[1];
                map<string,char>ma;
                for(int i=1;i<=m;++i){
                    fread(x,sizeof(char),1,fp);
                    fread(tlen,sizeof(char),1,fp);
                    fread(y,sizeof(ull),1,fp);
                    string ts="";
                    for(int j=tlen[0]-1;j>=0;--j){
                        ts+=(char)((y[0]>>j)&1);
                    }
                    ma[ts]=x[0];
                }
                memset(sp,0,sizeof(sp));
                fread(sp,sizeof(uc),N,fp);
                fclose(fp);
                string now="";
                FILE* fp2=fopen("test2.txt","w");
                int nn;
                for(int i=N+4;i>=0;--i){
                    if(sp[i]){
                        nn=i;
                        break;
                    }
                }
                puts("解压后的原文本为:");
                for(int i=0;i<nn;++i){
                    int lim=(i==nn-1 ? sp[nn] : 8);
                    for(int j=0;j<lim;++j){
                        now+=(char)((sp[i]>>(lim-1-j))&1);
                        if(ma[now]){
                            putchar(ma[now]);
                            fprintf(fp2,"%c",ma[now]);
                            now.clear();
                        }
                    }
                }
                fclose(fp2);
                puts("");
                printf("按任意键继续");
                while(!kbhit());
                ch=getch();
                if(ch==-32){
                    getch();
                }
            }
            else{
                break;
            }
        }
        return 0;
    }
    int ReadIn(FILE* fp){
        int len=0;
        while(!feof(fp)){
            fgets(s+len,N,fp);
            len+=strlen(s+len);
        }
        puts("原文本:");
        puts(s);
        return len;
    }
    void Freq_stats(){
        m=0;
        memset(cnts,0,sizeof(cnts));
        for(int i=0;i<n;++i){
            ++cnts[s[i]];
        }
        puts("各字符出现频率:");
        for(int i=0;i<256;++i){
            if(cnts[i]){
                table[m++]=(char)i;
                if(i!='
    '){
                    printf("%c %d
    ",i,cnts[i]);
                }
                else{
                    printf("\n %d
    ",cnts[i]);
                }
            }
        }
    }
    void dfs(int U,string s){
        if(U<256){
            anss[U]=s;
        }
        char c='0';
        for(ITER it=G[U].begin();it!=G[U].end();++it,++c){
            dfs(*it,s+c);
        }
    }
    void HuffmanCoding(){
        for(int i=0;i<512;++i){
            G[i].clear();
        }
        priority_queue<data,vector<data>,greater<data> >Heap;
        for(int i=0;i<256;++i){
            if(cnts[i]){
                Heap.push(make_pair(cnts[i],i));
            }
        }
        for(int i=1;i<m;++i){
            data x=Heap.top(); Heap.pop();
            data y=Heap.top(); Heap.pop();
            G[255+i].push_back(x.second);
            G[255+i].push_back(y.second);
            sort(G[255+i].begin(),G[255+i].end());
            Heap.push(data(x.first+y.first,255+i));
        }
        dfs(255+m-1,"");
        puts("给各个字符分配的零一编码:");
        for(int i=0;i<256;++i){
            if(cnts[i]){
                if(i!='
    '){
                    cout<<(char)i<<' '<<anss[i]<<endl;
                }
                else{
                    cout<<"\n "<<anss[i]<<endl;
                }
            }
        }
    }
  • 相关阅读:
    【剑指offer】面试题35:第一个只出现一次的字符
    【剑指offer】面试题34:丑数
    【剑指offer】面试题33:把数组排成最小的数
    【剑指offer】面试题32:从1到n整数中1出现的次数
    【剑指offer】面试题31:连续子数组的最大和
    【剑指offer】面试题30:最小的 k 个数
    【剑指offer】面试题29:数组中出现次数超过一半的数字
    【剑指offer】面试题28:字符串的排列
    【剑指offer】面试题27:二叉搜索树与双向链表
    【剑指offer】面试题26:复杂链表的复制
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/8151008.html
Copyright © 2011-2022 走看看