物联1132课程设计三

<h3 style="margin: 0px; padding: 0px; color: rgb(51, 51, 51); font-family: Arial; line-height: 26px;"><span style="font-size:24px;">在一个加密应用中,要处理的信息来自下面的字符集,各个字符的相关使用频度如下</span></h3><p style="color: rgb(51, 51, 51); font-family: Arial; line-height: 26px;"><span style="font-size:18px;"><span style="font-family: 微软雅黑, sans-serif; color: black;">字符</span><span style="font-family: 微软雅黑, sans-serif; color: black;"></span><span style="font-family: 微软雅黑, sans-serif; color: black;">空格</span><span lang="EN-US" style="font-family: 微软雅黑, sans-serif; color: black;">  A  B  C  D   E F  G  H I  J K  L M
</span><span style="font-family: 微软雅黑, sans-serif; color: black;">频度</span><span lang="EN-US" style="font-family: 微软雅黑, sans-serif; color: black;"> 180 64 13 23 32103 22 15  47 57  1 5 31  20
</span><span style="font-family: 微软雅黑, sans-serif; color: black;">字符</span><span style="font-family: 微软雅黑, sans-serif; color: black;"> <span lang="EN-US">N O P  Q R  S T  U V W X Y Z
</span></span><span style="font-family: 微软雅黑, sans-serif; color: black;">频度</span><span style="font-family: 微软雅黑, sans-serif; color: black;"> <span lang="EN-US">55 63 15 1 48 56 80 25 7 18 2  16  1
</span></span><span style="font-family: 微软雅黑, sans-serif;">现请编写程序你实现如下功能:</span></span></p><p style="color: rgb(51, 51, 51); font-family: Arial; line-height: 26px;"><span style="font-family: 微软雅黑, sans-serif;"><span style="font-size:18px;">(<span lang="EN-US">1</span>)运行时,由用户输入来初始化字符集大小和相应用字符。</span></span></p><p style="color: rgb(51, 51, 51); font-family: Arial; line-height: 26px;"><span style="font-family: 微软雅黑, sans-serif;"><span style="font-size:18px;">(<span lang="EN-US">2</span>)输入一个要加密的字符串,将其加密。</span></span></p><p style="color: rgb(51, 51, 51); font-family: Arial; line-height: 26px;"><span style="font-family: 微软雅黑, sans-serif;"><span style="font-size:18px;">(<span lang="EN-US">3</span>)输出解密字符串</span></span><span style="font-size: 9pt; font-family: 微软雅黑, sans-serif;">。</span></p>#include <iostream>  
using namespace std;  
#define MAX_FILE 5000//假设的文件最大长度  
#define MAXLIST 256//最大MAP值  
#define MAX_HOFFMAN_LENGTH 50//哈夫曼编码长度  
char dictionary[MAXLIST][2]={0};//Hash映射,[][0]为权值,[][1]为字符  
char fileContent[MAX_FILE];//处理的字符串大小  
int Hoffman[MAXLIST][MAX_HOFFMAN_LENGTH]={2};//哈夫曼编码序列  
char HoffmanList[MAXLIST]={0};//哈夫曼编码对应的字符有序序列  
char HoffFileCode[MAX_FILE]={0};//哈夫曼编码字符串序列  
char HoffFile[MAX_FILE]={0};  
//编码到假设的文件的哈夫曼压缩格式: 依次存储 原字符串长度(1字节存储:可扩展到2字节)、哈夫曼编码数(1字节)、每个哈夫曼编码的长度序列、每个哈夫曼编码对应的字符序列、编码过的哈夫曼字符串  
char GetFile[MAX_FILE]={0};//解码序列  
void ShellSort(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;  
          }  
        }  
}  
struct TNode//哈夫曼树结点  
{  
     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;  
     }  
};  
struct LNode//链表结点,用于存储哈夫曼树结点,进而构造哈夫曼树(保证每一步链表结点包含的哈夫曼结点都是有序的)  
{  
     LNode* prev;  
     LNode* next;  
     TNode* tnode;  
     LNode()  
     {  
          prev=next=0;  
          tnode=0;  
     }  
};  
int len=0;//哈夫曼编码数  
int deep=-1;//深度  
void Preorder(TNode * p);//前序遍历  
void byLeft(TNode*p)//经由左结点  
{  
     deep++;  
     Hoffman[len][deep]=0;  
     Preorder(p);  
     Hoffman[len][deep]=2;  
     deep--;  
}  
void byRight(TNode*p)//经由右结点  
{  
    deep++;  
    Hoffman[len][deep]=1;  
    Preorder(p);  
    Hoffman[len][deep]=2;  
    deep--;  
}  
void Preorder(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++;  
     }  
}  
char generateOne(int k)//产生k个连续1的二进制串,比如111,1111,111111,用于编码进假设的文件  
{  
     char c=0;  
     for(;k!=0;k--)  
     {  
          c|=(1<<(k-1));  
     }  
     return c;  
}  
int compareBits(char b1,char b2,char c,int l,int d)//判断由 [b1,b2]  组成的16位二进制数以d为起点,是否是长度为l的c二进制串(哈夫曼编码)的前缀  
{  
    unsigned __int8 t=(((((0x00ff&b1)<<8)|(0x00ff&b2))>>(8-d))&0x00ff);  
    return (((t)&((generateOne(l)<<(8-l))&0xff))==((c<<(8-l))&0xff));  
}  
int main()  
{  
   /*  或许假定的文件字符串向量中的字符串 */  
    cout<<"请输入要压缩的字符串:";  
    cin>>fileContent;  
    cin.get();  
    unsigned short fileLen=0;  
   /*  Hash进dictionary */  
    for(int i=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=new TNode(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=new TNode(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=new TNode('\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++)  
        {  
            int j=dictionary[fileContent[i]][0];  
            for(int k=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(int k=0;k!=HoffFile[1];k++)  
            {  
                char l=HoffFile[2+k],d=j%8,b1=HoffFile[j/8+2+HoffFile[1]*3],b2=HoffFile[j/8+1+2+HoffFile[1]*3];  
                char c=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(int i=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;  
}  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。在编写C程序时,需要注意变量的声明和定义、指针的使用、内存的分配与释放等问题。C语言中常用的数据结构包括: 1. 数组:一种存储同类型数据的结构,可以进行索引访问和修改。 2. 链表:一种存储不同类型数据的结构,每个节点包含数据和指向下一个节点的指针。 3. 栈:一种后进先出(LIFO)的数据结构,可以通过压入(push)和弹出(pop)操作进行数据的存储和取出。 4. 队列:一种先进先出(FIFO)的数据结构,可以通过入队(enqueue)和出队(dequeue)操作进行数据的存储和取出。 5. 树:一种存储具有父子关系的数据结构,可以通过中序遍历、前序遍历和后序遍历等方式进行数据的访问和修改。 6. 图:一种存储具有节点和边关系的数据结构,可以通过广度优先搜索、深度优先搜索等方式进行数据的访问和修改。 这些数据结构在C语言中都有相应的实现方式,可以应用于各种不同的场景。C语言中的各种数据结构都有其优缺点,下面列举一些常见的数据结构的优缺点: 数组: 优点:访问和修改元素的速度非常快,适用于需要频繁读取和修改数据的场合。 缺点:数组的长度是固定的,不适合存储大小不固定的动态数据,另外数组在内存中是连续分配的,当数组较大时可能会导致内存碎片化。 链表: 优点:可以方便地插入和删除元素,适用于需要频繁插入和删除数据的场合。 缺点:访问和修改元素的速度相对较慢,因为需要遍历链表找到指定的节点。 栈: 优点:后进先出(LIFO)的特性使得栈在处理递归和括号匹配等问题时非常方便。 缺点:栈的空间有限,当数据量较大时可能会导致栈溢出。 队列: 优点:先进先出(FIFO)的特性使得
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值