物联113208课程设计题目三
来源:互联网 发布:网络举报赌博举报电话 编辑:程序博客网 时间:2024/05/03 16:28
在一个加密应用中,要处理的信息来自下面的字符集,各个字符的相关使用频度如下
字符空格 A B C D E F G H I J K L M
频度 180 64 13 23 32103 22 15 47 57 1 5 31 20
字符 N O P Q R S T U V W X Y Z
频度 55 63 15 1 48 56 80 25 7 18 2 16 1
现请编写程序你实现如下功能:
(1)运行时,由用户输入来初始化字符集大小和相应用字符。
(2)输入一个要加密的字符串,将其加密。
(3)输出解密字符串。
分析
哈夫曼算法Huffman Tree
void HuffmanTree(element huffTree[],int w[],int n)
{
for(i=0;i<2*n-1;i++)
{
huffTree[i].parent=-1;
huffTree[i].lchild=-1;
huffTree[i].rchild=-1;
}
for(i=0;i<n;i++)
huffTree[i].weight=w[i];
for(k=n;k<2*n-1;k++)
{
Select(huffTree,i1,i2);
huffTree[i1].parent=k;
huffTree[i2].parent=k;
huffTree[k].weight=huffTree[i1].weight+huffTree[i2].weight;
huffTree[k].lchild=i1;
huffTree[k].rchild=i2;
}
}
程序及说明
#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;}
收获:懂得如何合理运用哈夫曼树原理和哈弗曼算法在c++的用法
体会:查找适当函数的旅途十分的艰辛,希望可以进一步强化自己的c++知识
不足:对程序的内部运行还不是很了解,应该一步一步地去了解c语言类程序的历史。
- 物联113208课程设计题目三
- 2008课程设计题目(三)
- 物联1132课程设计三
- 多媒体课程设计题目
- 操作系统课程设计题目
- Java课程设计题目
- 074《计算机网络课程设计》题目
- 医学院校计算机专业课程设计题目
- 数据结构课程设计题目
- Java课程设计题目
- 数据库课程设计题目
- 大学数据结构课程设计题目
- 《数据结构》课程设计题目
- 数据结构课程设计 题目4
- 题目二:课程设计报告
- 课程设计:题目2
- 题目3,课程设计
- 【课程设计】题目1
- C++ 类A调用类B的方法来修改自己的数据
- Vs2013在Linux开发中的应用(32):文本可视化
- Windows驱动开发开发环境搭建
- UNIX系统的文件类型
- JavaScript依赖注入的实现思路
- 物联113208课程设计题目三
- 67群组简单详情的完成
- JavaScript定义类,定义属性,定义方法的几种方式详解与分析
- 求两个排序数组的交集
- UPnP 设备描述文件和服务描述文件
- javascript中的this和prototype学习
- Chernoff bound(chernoff-hoeffding bound)
- OJ数组杨辉三角
- iOS UITextField Source Code, UITextField Open Source Code, UITextField Code Examples