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;
                }
            }
        }
    }
  • 相关阅读:
    172. Factorial Trailing Zeroes
    96. Unique Binary Search Trees
    95. Unique Binary Search Trees II
    91. Decode Ways
    LeetCode 328 奇偶链表
    LeetCode 72 编辑距离
    LeetCode 226 翻转二叉树
    LeetCode 79单词搜索
    LeetCode 198 打家劫舍
    LeetCode 504 七进制数
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/8151008.html
Copyright © 2011-2022 走看看