Huff_code.rar

  • 月西西
    了解作者
  • C/C++
    开发工具
  • 15MB
    文件大小
  • rar
    文件格式
  • 0
    收藏次数
  • 1 积分
    下载积分
  • 0
    下载次数
  • 2020-12-11 11:05
    上传日期
一个编程作业,利用huffman树对字母编码,应该挺好用的,可供大家参考
Huff_code.rar
内容介绍
#include"Huff_code.h" HTree Init(HTree T);/*建立包含26个字母及其权值的huffman树*/ void Build_file(HTree T);/*打开文件hfmTree并将构造好的树输入*/ char* ENcoding(char* p,HTree T,int &len_1,int &len_2);/*对指针p指向的字符串编码并建立codefile存储结果,同时返回表示码值的字符串,记录编码前长度与编码后长度*/ void out_file(char* p);/*文件输出,p表示文件名*/ char* DEcoding(HTree T);/*对指针p指向的二进制码进行解码并建立textfile存储结果,同时返回解码的字符串*/ bool flag=0;/*对编码(解码)是否成功进行标记*/ void Output(char *e); void output_all(HTree T); /*输出所有字母的编码*/ int main() { HTree c_table; c_table=Init(c_table); Build_file(c_table); char baowen[] = "THIS PROGRAM IS MY FAVORITE"; char* e = baowen; char bianma[400]; char* d = bianma; int len_1 = 0; int len_2 = 0; d = ENcoding(e, c_table,len_1, len_2); if (flag == 1) { flag = 0; e = DEcoding(c_table); } Output(e); cout << "编码前长度" << len_1 << '\t' << "编码后长度" << len_2 << '\n'; output_all(c_table); return 1; } HTree Init(HTree T) { char data[27]; int weight[27]={186,64,13,22,32,103,21,15,47,57,1,5,32,20,57,63,15,1,48,51,80,23,8,18,1,16,1}; data[0] = ' '; for (int i = 0; i < (26); i++) { data[i+1] = 'A' + i; } int i, k, s1, s2; int min1, min2; for (i = 0; i < MAX; i++) { T.Elem[i].data = data[i]; T.Elem[i].weight = weight[i]; T.Elem[i].parent = T.Elem[i].lchild = T.Elem[i].rchild = -1; } for (i = MAX; i <= 2*(MAX)-2; i++) { T.Elem[i].data = '\x2F'; T.Elem[i].parent = T.Elem[i].lchild = T.Elem[i].rchild = -1; /*初始化所有数据和相应权值、左右子节点*/ } for (i = MAX; i < 2 * MAX - 1; i++) /*huffman树的建立*/ { min1 = min2 = MAX_weight; s1 = s2 = 0; for (k = 0; k < i; k++) { if(T.Elem[k].parent==-1) if (T.Elem[k].weight < min1) { min2 = min1; s2 = s1; min1 = T.Elem[k].weight; s1 = k; } else if (T.Elem[k].weight < min2) { min2 = T.Elem[k].weight; s2 = k; } } T.Elem[s1].parent = T.Elem[s2].parent = i; T.Elem[i].lchild = s1; T.Elem[i].rchild = s2; T.Elem[i].weight = T.Elem[s1].weight + T.Elem[s2].weight; } T.num = MAX; T.root = 2 *( MAX) - 2; return T; } void Build_file(HTree T) { ofstream outfile("D:\\hfmTree.txt"); if (!outfile) { cout<<"can not open file htmTree"<<'\n'; } else { cout << "build is ready"<<'\n'; char ch ; int weight; for (int i = 0; i <= T.root; i++) { outfile << i << "号节点:"; weight = T.Elem[i].weight; outfile <<"权值"<<weight; ch = T.Elem[i].data; outfile << "数据" << ch << '\n'; outfile << "lchild" << " " << T.Elem[i].lchild << '\n'; outfile << "rchild" << " " << T.Elem[i].rchild << '\n'; } outfile.close(); } } char* ENcoding(char* p,HTree T,int &len_1,int &len_2) { ofstream outfile("D:\\codefile.txt"); bool fla = 1; if (!outfile) { cout << "can not open file codefile" << '\n'; fla = 0; } char bianma[400]; char* d = bianma; char t[100];/*临时储存反序编码*/ int bit = 0;/*记录编码位数*/ char* temp = t; for (int i = 0; p[i] != '\0'; i++)/*结束了一个字母的编码并输入codefile中,进行下一个字母的编码直到p字符串结束*/ { len_1++; int k = 0; for (k = 0; k < MAX; k++)/*找到对应字母的节点*/ { if (T.Elem[k].data == p[i]) { break; } } if (k == MAX) { cout << "编码失败,未找到对应字母" << '\n'; break; } for (int j = k; j != T.root && j < T.root;)/*从叶节点出发反向寻找根节点并记录反序的编码*/ { Node Parent = T.Elem[T.Elem[j].parent]; if (Parent.lchild == j) { *temp = 0 + '0'; } else { *temp = 1 + '0'; } temp++; bit++; j = T.Elem[j].parent; } cout << '\n'; for (int j2 = bit-1; j2 >= 0; j2--)/*将反序编码调正*/ { bianma[bit - 1 - j2] = t[j2]; if (fla) outfile << t[j2];/*将编码输入文件*/ len_2++; } bianma[bit] = '\0'; bit = 0; temp = &t[0];/*结束了一个字母的编码,进行下一个字母的编码*/ } flag = 1; outfile.close(); return d; } char* DEcoding(HTree T) { char tt[400]; /*几个数组的作用:tt[400]用来存放译码后的字母序列,q[1000]用来存放存储在文件中的二进制码*/ char* t = tt; char q[1000]; char* qq = q; ifstream infile("D:\\codefile.txt",ios::_Nocreate); if (!infile) { cout << "can not open file codefile" << '\n'; } else { cout << "成功打开codefile文件" << '\n'; char ch; int countt = 0; /*int ch用于文件输入输出,countt用来记录数组q(即文件中的二进制位数)大小*/ while (infile>>ch) { q[countt] = ch; cout << ch; /**/ countt++; } q[countt] = '\0'; infile.close(); ofstream outfile("D:\\textfile.txt"); bool fla = 1; if (!outfile) { cout << "can not open file textfile" << '\n'; fla = 0; } int i = 0;/*i记录转化后字母的个数即tt[]数组的大小*/ int k = T.root; int counttt; for (counttt = 0; counttt < countt;)/*counttt用来记录当前循环所到达的位置*/ { if (k < T.num) /*从根节点开始寻找,到第一个叶节点即视为找到编码对应字母,记录后继续寻找接下来编码对应的字母*/ { tt[i] = T.Elem[k].data; if (fla) outfile << tt[i]; /*如果成功打开textfile文件,则将对应字母输入*/ i++; k = T.root; continue; } if (q[counttt] == '0') k = T.Elem[k].lchild; if (q[counttt] == '1') k = T.Elem[k].rchild; counttt++; } tt[i] = T.Elem[k].data;/*将最后一位输出*/ if (fla) outfile << tt[i]; i++; outfile.close(); tt[i] = '\0'; cout << '\n' << t << '\n'; return t; } } void Output(char *e) { char name1[30] = "D:\\codefile.txt"; char name2[30] = "D:\\textfile.txt"; cout << "codefile" << "中的内容为:" << '\n'; out_file(name1); cout << "textfile" << "中的内容为:" << '\n'; out_file(name2); } void out_file(char* p) { char ch; ifstream infile(p); infile.unsetf(ios::skipws); if (!infile) { cout << "can not open file" << p << '\n'; } else { while (infile>>ch) { cout << ch; } cout << '\n'; } infile.close(); } void output_all(HTree T) { int bit = 0;/*bit表示编码长度*/ char bianma[100]; char* d = bianma; char t[100]; char* temp = t; for (int i = 0;i<27; i++) { for (int j = i; j != T.root && j < T.root;)/*从叶节点出发反向寻找根节点并记录反序的编码*/ { Node Parent = T.Elem[T.Elem[j].parent]; if (Parent.lchild == j) { *temp = 0 + '0'; } else { *temp = 1 + '0'; } temp++; bit++; j = T.Elem[j].parent; } for (int j2 = bit - 1; j2 >= 0; j2--)/*将反序编码调正*/ { bianma[bit - 1 - j2] = t[j2]; } bianma[bit] = '\0'; bit = 0; cout << T.Elem[i].data << "编码为" << d << '\n'; temp = &t[0];/*结束了一个字母的编码,进行下一个字母的编码*/ } }
评论
    相关推荐