数据结构实验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); //-------------------------------程序结果显示}

 

哈夫曼树的结构示例:
 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 我买东西没眼光怎么办 兔子身上有跳蚤怎么办 物业不提供发票怎么办 购房发票 不给怎么办 新锐大灯光散不聚怎么办 网络碰到垃圾人怎么办 有人侮辱我家人怎么办 亲人欠网贷还不上现在病重怎么办 亲人欠网贷现在病重怎么办 小孩子大嘴巴病怎么办 小孩子有心胀病怎么办 小孩子有胃痛病怎么办 大修基金用完了怎么办 基金买错了怎么办 基金公司倒闭了怎么办 桔子分期有风险怎么办 想买vivox21没钱怎么办 中介收钱不办事怎么办 手机应用程序几个运行怎么办 网上彩票是骗局怎么办 辞职后不想辞职怎么办 口头辞职后悔了怎么办 纸质承兑丢了怎么办 天天利财倒闭怎么办 网络理财平台诈骗怎么办 银行理财产品到期后怎么办 30岁没工作怎么办 理财投资被骗了怎么办 支付宝不想收钱怎么办 信融财富逾期怎么办 拼多多砍价上限怎么办 肺功能只有50%怎么办 办小商店营业执照怎么办 悉尼退税未到账怎么办 筋斗云钱包余额怎么办 在监狱得了癌症怎么办 国外客户不付款怎么办 日上免税店超额怎么办 淘宝评价被删怎么办 个人集资不还怎么办 淘宝达人扣54分怎么办?