数据结构实验4---用HuffmanTree进行编码、译码
来源:互联网 发布:数据保护线缠绕解 编辑:程序博客网 时间:2024/05/18 03:05
#include<iostream>#include<stdio.h>#include<fstream>#include<string>#include<string.h>#include<stdlib.h>#include<math.h>#define Status int #define OK 1 #define ERROR 0#define STACK_INIT_SIZE 10#define MAX_LINE 10#define MAX_CHAR 200using namespace std;typedef struct{ int weight, parent, lchild, rchild; char data;}ElemType;typedef struct{ ElemType * elem; int length; int listsize;}Sqlist;typedef char * * HuffmanCode;typedef struct{ char *base; char *top; int stacksize;}SqStack;Status InitStack(SqStack &s){//初始化栈函数。 s.base = (char *)malloc(STACK_INIT_SIZE * sizeof(char)); if(!s.base) exit(OVERFLOW); s.top = s.base; s.stacksize = STACK_INIT_SIZE; return OK;}Status push(SqStack &s, char e){//入栈函数。 if(s.top - s.base >= s.stacksize){ s.base = (char *)realloc(s.base, (s.stacksize + STACK_INIT_SIZE) * sizeof(char)); if(!s.base) exit(OVERFLOW); s.top = s.base + s.stacksize; s.stacksize += STACK_INIT_SIZE; } *s.top++ = e; return OK;}Status pop(SqStack &s, char &e){//出栈函数。 if(s.top == s.base) return ERROR; e = * --s.top; return OK;}Status emptystack(SqStack s){//判定栈空的函数。 if(s.base == s.top) return OK; else return ERROR;}void select(Sqlist HT, int i, int &s1, int &s2, static bool *flag){ //选择两个未被访问的最大的数组下标分别赋给s1, s2。 int n = (HT.listsize + 1)/2; int weight, xiabiao; //求第一个最大值。 for(int i = 0; i < HT.listsize; i++){ if(flag[i] != true){ weight = HT.elem[i].weight; xiabiao = i; break; } } for(int j = 1; j < i; j++){ if(HT.elem[j].weight < weight && flag[j] == false){ weight = HT.elem[j].weight; xiabiao = j; } } s1 = xiabiao; flag[s1] = true; //求第二个最大值。 for(int i = 0; i < HT.listsize; i++){ if(flag[i] != true){ weight = HT.elem[i].weight; xiabiao = i; break; } } for(int j = 1; j < i; j++){ if(HT.elem[j].weight < weight && flag[j] == false){ weight = HT.elem[j].weight; xiabiao = j; } } s2 = xiabiao; flag[s2] = true;}void CreateHuffmanTree(int n, int *w, Sqlist &HT, char *ch){ int m = 2 * n - 1; HT.elem = new ElemType[m]; HT.length = HT.listsize = m; for(int i = 0; i < n; i++){ HT.elem[i].weight = w[i]; HT.elem[i].parent = -1; HT.elem[i].lchild = -1; HT.elem[i].rchild = -1; HT.elem[i].data = ch[i]; } static bool *flag; flag = new bool[HT.listsize]; for(int i = 0; i < HT.listsize; i++){ flag[i] = false; } for(int i = n; i < m; i++){ int s1, s2; select(HT, i, s1, s2, flag); HT.elem[i].weight = HT.elem[s1].weight + HT.elem[s2].weight; HT.elem[i].parent = -1; HT.elem[i].lchild = s1; HT.elem[i].rchild = s2; HT.elem[s1].parent = i; HT.elem[s2].parent = i; } delete []flag;}Status HuffmanCoding(Sqlist HT, HuffmanCode &HC, int n){ SqStack s; InitStack(s); HC = new char* [n]; for(int i = 0; i < n; i++){ int j = i; while(HT.elem[j].parent != -1){ int parent = HT.elem[j].parent; if(HT.elem[parent].lchild == j){ push(s, '0'); }else{ push(s,'1'); } j = parent; } push(s, '\0'); HC[i] = new char[s.top - s.base]; strcpy(HC[i], s.base); strrev(HC[i]); s.top = s.base; } free(s.base); return OK;}void tongji(string filename, char *&ch, int *&w, int &n, char **&s, int &line){//文本内容只允许[a-z]和‘#’; //filename是打开文件名;ch是存放文本中出现的字符的数组; //w是存放对应的字符的weight的数组,n是出现的字符的个数 s = new char*[MAX_LINE]; ifstream in; in.open(filename, ios::in); string s1; static int count_Line = 0; for(int i = 0; getline(in, s1); i++){//要求文件行数小于10,每行字符数小于200 const char *s2; s2 = s1.c_str(); s[i] = new char[MAX_CHAR]; strcpy(s[i], s2); count_Line++; } line = count_Line; int *w1 = new int [27];//动态创建w1;加上一个'#‘; for(int i = 0; i < 27; i++){//把初始值设为0; w1[i] = 0; } for(int i = 0; i < count_Line; i++){ for(int j = 0; s[i][j] != '\0'; j++){ int t1 = s[i][j] - 'a';//假设只有小写字母 w1[t1]++; } } static int k = 0; ch = new char[28];//还包含一个’\0';//并且多预留一个空间存放'#'; int w2[27]; for(int i = 0; i < 27; i++){ if(w1[i]){ ch[k] = char('a' + i); w2[k] = w1[i]; ++k; } } w = new int[k + 1];//多预留一个空间存放‘#’的权值0; for(int i = 0; i < k; i++){ w[i] = w2[i]; } n = k + 1; w[k] = 0; ch[k] = '#'; ch[k + 1] = '\0'; in.close(); delete [] w1;}void bianma(char **s, HuffmanCode HC, char *ch, int line, int n){// ofstream out; out.open("temp.txt", ios::out);//这里先写死 for(int i = 0; i < line; i++){//只要小于行数,一直做; char *s2 = new char[400];//0100101010000型的字符 s2[0] = '/'; for(int j = 0; s[i][j] != '\0'; j++){ for(int k = 0; k < n; k++){ if(ch[k] == s[i][j]){ if(s2[0] == '/'){ strcpy(s2, HC[k]); }else{ //strcpy(s2, HC[k]); strcat(s2, HC[k]);//这样写没有问题 } //cout<<s2<<endl;//ceshi } } } //char *s3 = new char[s2.length() + 1];//动态创建s3; //strcpy(s3, s2.c_str());//10000101010类型的字符 int n1; static int count1 = 0; int intofchar = 0; char s4 = ' '; int char_to_int(char *cstr1, static int &count1,int &intofchar, int n, HuffmanCode HC); int flag; // delete [] s3;//动态销毁s3; cout<<"bianma "<<s2<<endl;//ceshi while(flag = char_to_int(s2, count1, intofchar, n, HC)){//此处为赋值 s4 = (char)(intofchar);//可以转但是char只有0-127,而s4为0-255,所以把s4同样改成‘7’位,即0-127 out<<s4;//输出到文本 } s4 = (char)(intofchar);//可以转但是char只有0-127,而s4为0-255,所以把s4同样改成‘7’位,即0-127 out<<s4;//输出到文本 out<<'\n'; count1 = 0; delete [] s2; } out.close();}void bianli(Sqlist HT, char *s2, int n){ ofstream out; out.open("data2.txt", ios::app); int static m; m = 2 * n - 1 - 1; for(int i = 0; s2[i] != '\0'; i++){ if(s2[i] == '0' && HT.elem[m].lchild == -1){ if(HT.elem[m].data != '#'){ out<<HT.elem[m].data; i = i - 1; m = 2 * n - 1 - 1; }else{ return; } }else if(s2[i] == '1' && HT.elem[m].rchild == -1){ if(HT.elem[m].data != '#'){ out<<HT.elem[m].data; i = i - 1; m = 2 * n - 1 - 1; }else{ return; } }else if(s2[i] == '1'){ m = HT.elem[m].rchild; }else{ m = HT.elem[m].lchild; } } out.close(); return;}void jiema(Sqlist HT, int n){//jieguo是解码之后的内容,可以在控制台打印,也可以存到文件中; ifstream in; string str1; in.open("temp.txt", ios::in); while(getline(in, str1)){ char* int_to_char(string str1);//函数声明 char *s2 = int_to_char(str1); cout<<"jiema "<<s2<<endl;//测试 bianli( HT, s2, n); ofstream out; out.open("data2.txt", ios::app); out<<'\n'; out.close(); delete [] s2; } in.close();}int char_to_int(char *cstr1, static int &count1, int &intofchar, int n, HuffmanCode HC){ int x; intofchar = 0; for(x = count1; cstr1[x] != '\0'&& x - count1 < 7; x++){ if(cstr1[x] == '1'){ intofchar = intofchar + (int)(pow(double(2), (7 - (x - count1) - 1))); } } if(x - count1 != 7){ for(int z = 0; z < 7 - (x - count1); z++){ if(HC[n - 1][z] == 1){ intofchar = intofchar + (int)(pow(double(2), (7 - (x - count1) - z))); } } return 0; }else{ count1 = count1 + 7; return 1; }}char* int_to_char(string str1){//ok char *s1 = new char[str1.length() + 1]; strcpy(s1, str1.c_str()); char *s2 = new char[700];//存放0101010001011100100010010001010型的字符串; int t1 = char(s1[0]);//第一次的时候用strcpy char s3[8]; int i = 0; for( ; t1 / 2 != 0; i++){ if(t1 % 2 == 0){ s3[i] = '0'; }else{ s3[i] = '1'; } t1 = t1 / 2; } s3[i] = '1'; if(i != 7){ while(i < 6){ s3[i] = '0'; i++; } } s3[7] = '\0'; strrev(s3); strcpy(s2,s3); for(int j = 1; s1[j] != '\0'; j++){//后面的用循环,用strcat int t1 = char(s1[j]); char s3[8]; i = 0; for( ; t1 / 2 != 0; i++){ if(t1 % 2 == 0){ s3[i] = '0'; }else{ s3[i] = '1'; } t1 = t1 / 2; } s3[i] = '1'; if(i != 7){ while(i < 6){ s3[i] = '0'; i++; } } s3[7] = '\0'; strrev(s3); strcat(s2,s3); } delete [] s1; return s2;}int main(){//主函数。 //-------------------测试HuffmanTree和HuffmanCode //int n; //Sqlist HT; //HuffmanCode HC; ////读文件。 //fstream in; //in.open("jiedian.txt", ios::in); //in>>n;//读入data的个数 //int *w = new int[n]; //char *ch = new char[n]; //for(int i = 0; i < n; i++){//读入datas // in>>ch[i]; //} //for(int i = 0; i < n; i++){//读入weights // in>>w[i]; //} ////关闭文件。 //CreateHuffmanTree(n, w, HT,ch); //HuffmanCoding(HT, HC, n); //for(int i = 0; i < n; i++){//ceshi // cout<<"code i = "<<i<<": "<<HC[i]<<endl; //} //in.close(); //delete [] w; //delete [] HT.elem; //delete [] *HC; //delete [] HC; //-----------------------------测试结束 //-----------------------------程序结果显示 char *ch = NULL; int *w = NULL; int n = 0; int line = 0; string filename = "data1.txt";//data1.txt是待编码的文本 char **s; tongji(filename, ch, w, n, s, line); HuffmanCode HC; Sqlist HT; CreateHuffmanTree(n, w, HT,ch); HuffmanCoding(HT, HC, n); //for(int i = 0; i < n + 1; i++){//ceshi // cout<<ch[i]<<" "<<HC[i]<<endl; //} bianma(s, HC, ch, line, n); jiema(HT, n); //-------------------------------程序结果显示}
哈夫曼树的结构示例:
- 数据结构实验4---用HuffmanTree进行编码、译码
- 数据结构实验,哈夫曼编码/译码系统
- 【数据结构实验】哈夫曼编/译码
- 数据结构实验2(设计哈弗曼编码和译码系统)
- 数据结构Huffman编码译码
- 数据结构课程设计-哈夫曼编码译码
- 【数据结构】哈夫曼树实现编码译码
- 南邮数据结构实验二——哈夫曼编码/译码系统
- 哈夫曼编码/译码(实验文档)
- 哈夫曼树构建,编码,译码的实现------数据结构
- 哈夫曼编码译码(数据结构课程设计)
- 数据结构课程设计——编码与译码
- 数据结构:哈夫曼树,哈夫曼编码与译码系统
- 【数据结构】哈夫曼树及哈夫曼编码译码
- 【数据结构基础】哈夫曼编码/译码课程设计
- 南邮数据结构实验二---二叉树的基本操作及哈夫曼编码译码系统的实现
- HuffmanTree以及其编码
- 数据结构.哈夫曼树(HuffmanTree)
- HTTP深入浅出http请求
- usaco2.13Healthy Holsteins(dfs枚举)
- Configure: error: XML configuration could not be found 解决办法
- UEFI Win7安装U盘的制作方式
- cocoa的NSNotification通知
- 数据结构实验4---用HuffmanTree进行编码、译码
- 在Linux里设置环境变量的方法(export PATH)
- Java面试笔试题大汇总
- linux ls命令 目录下文件太多
- 科普:手机电池的保护电路
- 有目的的活着-活的精彩
- wince 学习笔记3 sqlite的应用和操作
- 解决 error: cannot find openssl s 问题
- WPF入门系列教程(二) 深入剖析WPF Binding的使用方法