《数据结构课程设计》3号题

数据结构课程设计

   物联网工程1132班               201311672233               张志伟

一.   题目要求

题目3.

在一个加密应用中,要处理的信息来自下面的字符集,各个字符的相关使用频度如下:

字符 空格  A  B  C  D   E  F  G   H   I   J  K  L M

频度 180  64 13 23 32 103 22 15  47 57  15  31  20

 

字符  N  O   P    Q  R  S T   U  V  W  X  Y  Z 

频度  55 63  151 48  56  80 25 7  18  2  16  1

二.程序如下

#include<iostream> 

usingnamespace std; 

#defineMAX_FILE 5000//假设的文件最大长度 

#defineMAXLIST 256//最大MAP值 

#defineMAX_HOFFMAN_LENGTH 50//哈夫曼编码长度 

chardictionary[MAXLIST][2]={0};//Hash映射,[][0]为权值,[][1]为字符 

charfileContent[MAX_FILE];//处理的字符串大小 

intHoffman[MAXLIST][MAX_HOFFMAN_LENGTH]={2};//哈夫曼编码序列 

charHoffmanList[MAXLIST]={0};//哈夫曼编码对应的字符有序序列 

charHoffFileCode[MAX_FILE]={0};//哈夫曼编码字符串序列 

charHoffFile[MAX_FILE]={0}; 

//编码到假设的文件的哈夫曼压缩格式: 依次存储 原字符串长度(1字节存储:可扩展到2字节)、哈夫曼编码数(1字节)、每个哈夫曼编码的长度序列、每个哈夫曼编码对应的字符序列、编码过的哈夫曼字符串 

charGetFile[MAX_FILE]={0};//解码序列 

voidShellSort(char pData[MAXLIST][2],int Count)//Shell排序,用于准备有序化要构造的编码权值构造哈夫曼树做准备 

    int step[4]={9,5,3,1};//增量序列 

    int iTemp,cTemp; 

    int k,s,w; 

    for(int i=0;i<4;i++) 

        { 

          k=step[i]; 

          s=-k; 

          for(int j=k;j<Count;j++) 

          { 

              iTemp=pData[j][0]; 

              cTemp=pData[j][1]; 

              w=j-k; 

              if(s==0) 

              { 

                  s=-k; 

                  s++; 

                  pData[s][0]=iTemp; 

                  pData[s][1]=cTemp; 

              } 

             while((iTemp<pData[w][0])&&(w>=0)&&(w<=Count)) 

              { 

                  pData[w+k][0]=pData[w][0];//权值交换 

                  pData[w+k][1]=pData[w][1];//字符交换 

                  w=w-k; 

              } 

              pData[w+k][0]=iTemp; 

              pData[w+k][1]=cTemp; 

          } 

        } 

structTNode//哈夫曼树结点 

     TNode* pNode; 

     TNode* lNode; 

     TNode* rNode; 

     char dictionary; 

     char weight;  

     TNode(char dic,char wei) 

     { 

         pNode=0; 

         lNode=0; 

         rNode=0; 

         dictionary=dic; 

         weight=wei; 

     } 

}; 

structLNode//链表结点,用于存储哈夫曼树结点,进而构造哈夫曼树(保证每一步链表结点包含的哈夫曼结点都是有序的) 

     LNode* prev; 

     LNode* next; 

     TNode* tnode; 

     LNode() 

     { 

          prev=next=0; 

          tnode=0; 

     } 

}; 

intlen=0;//哈夫曼编码数 

intdeep=-1;//深度 

voidPreorder(TNode * p);//前序遍历 

voidbyLeft(TNode*p)//经由左结点 

     deep++; 

     Hoffman[len][deep]=0; 

     Preorder(p); 

     Hoffman[len][deep]=2; 

     deep--; 

voidbyRight(TNode*p)//经由右结点 

    deep++; 

    Hoffman[len][deep]=1; 

    Preorder(p); 

    Hoffman[len][deep]=2; 

    deep--; 

voidPreorder(TNode * p) 

     if(p->lNode!=0)//当左子结点非空则遍历 

     { 

          byLeft(p->lNode); 

     } 

     if(p->rNode!=0)//当右子结点非空则遍历 

     { 

          byRight(p->rNode); 

     } 

    if((p->lNode==0)&&(p->rNode==0))//当左右结点都为空,则增加哈夫曼编码数到另一个记录 

     { 

          Hoffman[len][deep+1]=2; 

          int i=0; 

          for(;Hoffman[len][i]!=2;i++) 

          { 

             Hoffman[len+1][i]=Hoffman[len][i]; 

          } 

          Hoffman[len+1][i]=2; 

         HoffmanList[len]=p->dictionary; 

          len++; 

     } 

chargenerateOne(int k)//产生k个连续1的二进制串,比如111,1111,111111,用于编码进假设的文件 

     char c=0; 

     for(;k!=0;k--) 

     { 

          c|=(1<<(k-1)); 

     } 

     return c; 

intcompareBits(char b1,char b2,char c,int l,int d)//判断由 [b1,b2]  组成的16位二进制数以d为起点,是否是长度为l的c二进制串(哈夫曼编码)的前缀 

    unsigned __int8t=(((((0x00ff&b1)<<8)|(0x00ff&b2))>>(8-d))&0x00ff); 

    return(((t)&((generateOne(l)<<(8-l))&0xff))==((c<<(8-l))&0xff)); 

intmain() 

   /*  或许假定的文件字符串向量中的字符串 */ 

    cout<<"请输入要压缩的字符串:"; 

    cin>>fileContent; 

    cin.get(); 

    unsigned short fileLen=0; 

   /* Hash进dictionary */ 

    for(inti=0;fileContent[i]!='\0';i++,fileLen++) 

    { 

        ++dictionary[fileContent[i]][0]; 

       dictionary[fileContent[i]][1]=fileContent[i]; 

    } 

    int len=0; 

   /*  把Hash了的dictionary向前靠拢 */ 

    { 

        for(int i=0;i!=MAXLIST;i++) 

        { 

             if(dictionary[i][0]!=0) 

             { 

                dictionary[len][0]=dictionary[i][0]; 

                dictionary[len][1]=dictionary[i][1]; 

                 len++; 

             } 

        } 

    } 

    cout<<"哈夫曼编码个数:"<<len<<endl; 

   /*  对dictionary按权值进行排序 */ 

    ShellSort(dictionary,len); 

   /* 构造链表,链表中放有序dictionary权值的树结点 */ 

    LNode* head=new LNode,*p=head; 

    head->next=new LNode; 

    TNode *tempTNode=newTNode(dictionary[0][1],dictionary[0][0]); 

    head->tnode=tempTNode; 

    { 

        for(int i=0;i!=len-1;i++) 

        { 

           p->next->prev=p->next; 

            p=p->next; 

            p->next=new LNode; 

            tempTNode=newTNode(dictionary[i+1][1],dictionary[i+1][0]); 

            p->tnode=tempTNode; 

        } 

    } 

    delete p->next; 

    p->next=0; 

   /* 每次最小权值的前面两个链表结点中的树结点组成一个子树,子树有合权值,子数的根按权值排序进链表*/ 

    for(p=head;p->next!=0;) 

    { 

       p->tnode->pNode=newTNode('\0',(p->tnode->weight)+(p->next->tnode->weight)); 

       p->next->tnode->pNode=p->tnode->pNode; 

       p->tnode->pNode->lNode=p->tnode; 

       p->tnode->pNode->rNode=p->next->tnode; 

        head=p->next; 

        delete p; 

        p=head; 

        p->tnode=p->tnode->pNode; 

        for(LNode*t=head;t->next!=0;t=t->next) 

        { 

           if(t->tnode->weight>t->next->tnode->weight) 

            { 

                TNode* k=t->tnode; 

               t->tnode=t->next->tnode; 

                t->next->tnode=k; 

            } 

        } 

    } 

    int code[500],h=0; 

   /* 前序遍历构造哈夫曼编码*/ 

    Preorder(p->tnode); 

    { 

        for(int i=0;i!=len;i++) 

            dictionary[HoffmanList[i]][0]=i; 

    } 

   /* 存储字符串的哈夫曼压缩编码串,并且打包文件格式 */ 

    int codeLen=0,total=0; 

    { 

        for(int i=0;i!=fileLen;i++) 

        { 

            intj=dictionary[fileContent[i]][0]; 

            for(intk=0;Hoffman[j][k]!=2;k++) 

            { 

               HoffFileCode[codeLen]|=(Hoffman[j][k]<<(7-total%8)); 

                code[h++]=Hoffman[j][k]; 

                if(((total+1)%8)==0) 

                { 

                   HoffFile[1+len*3+1+codeLen]=HoffFileCode[codeLen]; 

                    codeLen++; 

                } 

                total++; 

            } 

        } 

    } 

   HoffFile[1+len*3+1+codeLen]=HoffFileCode[codeLen]; 

    HoffFile[0]=(fileLen); 

   /* 解压缩假定的文件HoffFile成为原字符串序列 */ 

    cout<<"哈夫曼编码序列:\n"; 

    HoffFile[1]=len; 

    { 

        for(int i=0,j=0;i!=len;i++,j=0) 

        { 

            for(;Hoffman[i][j]!=2;j++); 

            HoffFile[i+2]=j; 

           HoffFile[i+2+2*len]=HoffmanList[i]; 

            for(int k=0;k!=j;k++) 

            { 

                cout<<Hoffman[i][k]; 

               HoffFile[i+2+len]|=(Hoffman[i][k]<<(j-1-k)); 

            } 

           cout<<":"<<HoffmanList[i]<<endl; 

        } 

 

    } 

    { 

        for(int i=0,j=0;i!=(HoffFile[0]&0xff);i++) 

        { 

            for(intk=0;k!=HoffFile[1];k++) 

            { 

                charl=HoffFile[2+k],d=j%8,b1=HoffFile[j/8+2+HoffFile[1]*3],b2=HoffFile[j/8+1+2+HoffFile[1]*3]; 

                charc=HoffFile[HoffFile[1]+2+k]; 

               if(compareBits(b1,b2,c,l,d)) 

                { 

                    j+=HoffFile[2+k]; 

                   GetFile[i]=HoffFile[2+HoffFile[1]*2+k]; 

                    break; 

                } 

            } 

        } 

    } 

    { 

        cout<<"哈夫曼压缩后二进制序列:"<<endl; 

        for(int i=0;i!=h;i++) 

        { 

            cout<<code[i]; 

            if((i+1)%8==0) 

            cout<<" "; 

        } 

    } 

    cout<<endl; 

    { 

        cout<<"哈夫曼压缩打包假定文件格式二进制的文本体现:"; 

        cout<<endl; 

        for(inti=0;i!=HoffFile[0]+HoffFile[1]*3;i++) 

        { 

            cout<<HoffFile[i]; 

        } 

        cout<<endl; 

    } 

    cout<<"原字节数为:"<<fileLen<<endl; 

    cout<<"压缩后字节数为:"<<(h)/8+1<<endl; 

    cout<<"压缩率为"<<((h/8.0+1)/fileLen)*100<<"%"<<endl; 

    { 

        cout<<"字符串字节数为:"<<(HoffFile[0]&0xff)<<endl; 

        cout<<"字符串解压序列为:"; 

        for(int i=0;i!=(HoffFile[0]&0xff);i++) 

        { 

            cout<<GetFile[i]; 

        } 

        cout<<endl; 

        cin.get(); 

    } 

    return 1; 

 

三.程序调试


四.心得体会

程序设计真正做起来不会很难也不简单,如果没有去学的话,做起来肯定是很难的,因为程序设计相对来说比较抽象,有时候难以理解。本程序参考了一些其他好的程序,其中重要部分做了补充和完善,不过程序依然存在很多不足。学习数据结构的时候,对于一些程序的实现感觉很奇妙,对于一些不懂的也很迷茫,总的来说就是只要认真学,什么都可以学得会。我个人比较懒,以后会尽量保持学习的积极主动,学多点知识,不虚度光阴!虽然期末到了,数据结构的课程结束了,但数据结构的学习还会继续……


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值