qq_35190965 2016-06-01 12:00 采纳率: 0%
浏览 3290

数据结构,哈夫曼编码,文件压缩和解压缩一个完整的程序

数据结构,哈夫曼编码,文件压缩和解压缩一个完整的程序,大神们最好能带点注释,简单点的就行。重点:哈夫曼编码,文件压缩和解压缩

  • 写回答

1条回答 默认 最新

  • 小灸舞 2016-06-01 13:21
    关注
     #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<conio.h>
    
    #define MAXNUM 60
    
    typedef struct
    {
        char ch;
        int weight; //权值,这个字符出现的频率
        int parent;
        int left;
        int right;
    }HuffNode;
    
    typedef struct
    {
        char code[MAXNUM];
        int start;
    }HuffCode;
    
    HuffNode ht[MAXNUM*2]; //存放哈夫曼树
    
    HuffCode hcd[MAXNUM];  //存放ht数组中对应的字符的编码
    
    int n;                 //字符的个数
    
    //初始化哈夫曼树ht
    void initHt()
    {
        FILE * fp;
        char ch;
        int i=0;
        //从文件document/character.txt中读出要编码的字符和权值
        if((fp=fopen("document/character.txt","r"))==NULL){
            printf("can not open the file character.txt");
            exit(0);
        }
        ht[i].left=ht[i].right=ht[i].parent=-1;
        while((ch=fgetc(fp))!=EOF){
            if(ch=='\n'){
                i++;
                ht[i].left=ht[i].right=ht[i].parent=-1;     
            }
            else if((ch>='a' && ch<='z')||(ch>='A' && ch<='Z'))
                ht[i].ch=ch;
            else if(ch>='0'&&ch<='9')
                ht[i].weight=ht[i].weight*10+ch-'0';
        }
        n=i+1;
        if(fclose(fp)){
            printf("can not close the file character.txt");
            exit(0);
        }
    }
    
    //构造哈夫曼树,看成有n棵树,选择权值最小的两棵树合并
    void createHuffTree()
    {
    
        int i=0,k;
        int minI,minJ;
        int f=0;
        minI=minJ=-1; //minI<minJ
        for(k=n;k<2*n-1;k++){
            //寻找ht中权值最小且无父结点的两个结点
            i=0;
            f=0;
            while(ht[i].ch!='\0'){
                if(ht[i].parent==-1){
                    if(f==0){
                        minI=i;
                        f++;
                    }else if(f==1){
                        if(ht[i].weight<ht[minI].weight){
                            minJ=minI;
                            minI=i;
                        }else
                            minJ=i;
                        f++;
                    }else{
                        if(ht[i].weight<ht[minI].weight){
                            minJ=minI;
                            minI=i;
                        }else if(ht[i].weight<ht[minJ].weight)
                            minJ=i;
                    }
                }
                i++;
            }
            //合并两个结点
            ht[k].ch='#';
            ht[k].left=minI;
            ht[k].right=minJ;
            ht[k].weight=ht[minI].weight+ht[minJ].weight;
            ht[k].parent=-1;
            ht[minI].parent=ht[minJ].parent=k;
        }
    }
    
    //将一个字符串反转
    void reverse(char *str)
    {
        int i,j;
        char ch;
        for(i=0,j=strlen(str)-1;i<j;i++,j--){
            ch=str[i];
            str[i]=str[j];
            str[j]=ch;
        }
    }
    
    //哈夫曼编码,通过父节点从下往上找
    void createHuffCode()
    {
        int i,j,length;
        FILE * fp;
        for(i=0;i<n;i++){
            length=0;
            j=i;
            //给每个字符进行编码
            while(ht[j].parent!=-1){
                if(ht[ht[j].parent].left==j){
                    hcd[i].code[length++]=0+'0';
                }else
                    hcd[i].code[length++]=1+'0';
                j=ht[j].parent;
            }
    
            hcd[i].start=hcd[i].code[length-1]-'0';
            hcd[i].code[length]='\0';
            reverse(hcd[i].code);
        }
        //把hcd字符编码写入文件document/code.txt中
        if((fp=fopen("document/code.txt","w"))==NULL){
            printf("can not open the file character.txt");
            exit(0);
        }
        for(i=0;i<n;i++){
            fputc(ht[i].ch,fp);
            fputs("    ",fp);
            fputs(hcd[i].code,fp);
            fputc('\n',fp);
        }
        if(fclose(fp)){
            printf("can not close the file character.txt");
            exit(0);
        }
    }
    
    //哈夫曼解码,每次都从根节点开始搜索
    int releaseHuffCode(char *str,char* code)
    {
        int root=2*n-2;
        int length=0,i=0;
        while(code[i]){
            if(code[i]=='0'+0)
                root=ht[root].left;
            else if(code[i]=='0'+1)
                root=ht[root].right;
            else
                return 0;
            if(ht[root].left==-1 && ht[root].right==-1){
                str[length++]=ht[root].ch;
                root=2*n-2;
            }
            i++;
        }
        str[length]='\0';
        if(root==2*n-2)
            return 1;
        return 0;
    }
    
    //用户输入编码字符
    void encode()
    {
        int i=0,j,f=1;
        char str[50];
        char code[500]={'\0'};
        printf("\n请输入要编码的字符串(length<50)\n");
        scanf("%s",str);
        while(str[i]){
            if((str[i]>='a'&&str[i]<='z')||(str[i]>='A'&&str[i]<='Z')){
                for(j=0;j<n;j++)
                    if(str[i]==ht[j].ch){
                        strcat(code,hcd[j].code);
                        break;
                    }
                    i++;
            }else{
                f=0;
                break;
            }
        }
        if(f)
            puts(code);
        else
            printf("你输入的字符串错误!\n");
        printf("按任意键后重新选择!\n");
        getch();
    }
    
    //用户输入解码字串
    void  decode()
    {
        char str[50];
        char code[500];
        printf("\n请输入要解码的字串(用0和1表示)\n");
        scanf("%s",code);
        if(releaseHuffCode(str,code))
            puts(str);
        else
            printf("你输入的字串错误!\n");
    
        printf("按任意键后重新选择!\n");
        getch();
    }
    
    //主函数
    void main()
    {
        int choice=1;
        initHt();
        createHuffTree();
        createHuffCode();
        while(choice){
            system("cls"); 
            printf("/****************哈夫曼编码与解码*********************/\n");
            printf(" 在document/character.txt 文件中存放着各个字母的权值\n");
            printf(" 程序从中读出各个字母的权值构造哈夫曼树并进行编码\n");
            printf(" 各个字符的编码存在document/code.txt文件中\n");
            printf("/*****************************************************/\n");
            printf("\n请输入你的选择:1 ---- 编码  2 ---- 解码  0 ---- 退出\n");
            scanf("%d",&choice);
            switch(choice){
            case 1: 
                encode();
                break;
            case 2: 
                decode();
                break;
            case 0: 
                printf("谢谢使用!\n");
                break;
            default:
                choice=1;
                printf("你的输入错误!按任意键后重新输入!\n");
                getch();
                break;
            }
        }
    }
    
    评论

报告相同问题?

悬赏问题

  • ¥100 求数学坐标画圆以及直线的算法
  • ¥35 平滑拟合曲线该如何生成
  • ¥100 c语言,请帮蒟蒻写一个题的范例作参考
  • ¥15 名为“Product”的列已属于此 DataTable
  • ¥15 安卓adb backup备份应用数据失败
  • ¥15 eclipse运行项目时遇到的问题
  • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
  • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
  • ¥15 自己瞎改改,结果现在又运行不了了
  • ¥15 链式存储应该如何解决