Haffman编码/译码——数据结构作业(二)
2016-01-11 11:45
465 查看
算法:Haffman,DFS
数据结构:queue,Haffman Tree
PS:使用链表建树,但用数组存树操作更方便
数据结构:queue,Haffman Tree
PS:使用链表建树,但用数组存树操作更方便
// Huffman.cpp : 定义控制台应用程序的入口点。 // //#include "stdafx.h" #include "iostream" #include "stdio.h" #include "stdlib.h" #include "string.h" #include "string" #include "queue" #include "fstream" const int max_nodenum=100; //最多字符数 using namespace std; struct Node { char ch; double weight; Node* parent; Node* Lchild; Node* Rchild; Node() { ch = NULL; weight = 0; parent = NULL; Lchild = NULL; Rchild = NULL; } bool operator < (const Node &a)const { return a.weight < weight; } }Hf[max_nodenum]; //Hf 用来存储符号信息,和建树无关 struct Info //打表保存字符编码信息 { char ch; string code; }info[max_nodenum]; Node *root; //huffman树根 void CreateTree() { root = new Node; priority_queue <Node> Queue; ifstream fin("hfmTree.txt"); //在文件中读取已保存的数据 int n; fin >> n; for (int i = 0; i < n; i++) { fin >> Hf[i].ch >> Hf[i].weight; Queue.push(Hf[i]); } while (Queue.size() > 1) //建树 从下向上 { Node* a = new Node; //左子树 if (Queue.top().ch == NULL) { *a = Queue.top(); a->Lchild->parent = a; //***被坑了好久 a->Rchild->parent = a; //*** } a->ch = Queue.top().ch; a->weight = Queue.top().weight; Queue.pop(); Node *b = new Node; //右子树 if (Queue.top().ch == NULL) { *b = Queue.top(); b->Lchild->parent = b; //*** b->Rchild->parent = b; //*** } b->ch = Queue.top().ch; b->weight = Queue.top().weight; Queue.pop(); Node *ab = new Node; //父节点 ab->weight = a->weight + b->weight; ab->Lchild = a; ab->Rchild = b; a->parent = ab; b->parent = ab; Queue.push(*ab); if (Queue.size() == 1) root = ab; //树根 } } void Initial() { int choose; cout << "建树:1.在控制台输入 2.在'hfmTree.txt'文件中读取" << endl; cin >> choose; if (choose == 1) { ofstream fclear("hfmTree.txt", std::ofstream::out | std::ofstream::trunc); //清空原有文件 cout << "控制台建树:输入字符集大小 n" << endl; ofstream fout("hfmTree.txt"); //在文件中输出 int n; cin >> n; fout << n << endl; cout << "输入:字符 权值" << endl; for (int i = 0; i < n; i++) //输入并输出到文件 { cin >> Hf[i].ch >> Hf[i].weight; fout << Hf[i].ch << " " << Hf[i].weight << endl; } CreateTree(); //文件中读取数据建树 cout << "建树成功,并保存到 'hfmTree.txt'中" << endl; } else if (choose == 2) { CreateTree(); //文件中读取数据建树 //cout << root->weight << " " << root->Lchild->parent->weight; cout << "文件中读取数据建树成功" << endl; } /* 4 a 5 s 10 d 15 f 10 */ } /*void tv(Node* rot) { cout << rot->weight << " " << rot->ch << endl; if (rot->Lchild == NULL && rot->Rchild == NULL) return; //if(rot->ch!=NULL) if(rot->Lchild!=NULL) tv(rot->Lchild); if(rot->Rchild!=NULL) tv(rot->Rchild); }*/ int info_num = 0; //字符编码信息数量 void Traverse(Node *rot) { if (rot->Lchild == NULL && rot->Rchild == NULL) { info[info_num].ch = rot->ch; Node* cur=rot; //cout << cur->weight << " " << cur->parent->parent->weight; while (cur->parent!=NULL) { //cout << cur->weight << " "<<cur->parent->weight; if (cur->parent->Lchild == cur) { info[info_num].code += '0'; } if (cur->parent->Rchild == cur) { info[info_num].code += '1'; } cur=cur->parent; } //cout << info[info_num].ch << " " << info[info_num].code << endl; int codelen = info[info_num].code.length(); for (int i = 0; i < codelen/2; i++) //逆置得正序编码 { int temp = info[info_num].code[i]; info[info_num].code[i] = info[info_num].code[codelen - i - 1]; info[info_num].code[codelen - i - 1] = temp; } info_num++; return; } if (rot->Lchild != NULL) Traverse(rot->Lchild); if(rot->Rchild!=NULL) Traverse(rot->Rchild); } void Encoding() { info_num = 0; memset(info, 0, sizeof(info)); //初始化 Traverse(root); //遍历打表记录编码映射 cout << "编码映射如下:" << endl; for (int i = 0; i < info_num; i++) { cout << info[i].ch << " " << info[i].code << endl; } //tv(root); cout << "编码:1.控制台输入数据 2.从文件'ToBeTran.txt'中读取" << endl; int choose; cin >> choose; ofstream fout("CodeFile.txt"); //编码结果保存文件 if (choose == 1) { cout << "输入字符序列:" << endl; string str; cin >> str; //Traverse(root); //cout << 111000; /* for (int i = 0; i < info_num; i++) { cout << info[i].ch<<" "; cout << info[i].code<<endl; } */ for (int i = 0; i < str.length(); i++) { for (int j = 0; j < info_num; j++) { if (str[i] == info[j].ch) { cout << info[j].code; fout << info[j].code; } } } cout << endl; cout << "以上编码结果已保存到文件'CodeFile.txt'中" << endl; } else if (choose == 2) { ifstream fin("ToBeTran.txt"); string str; fin >> str; //Traverse(root); for (int i = 0; i < str.length(); i++) { for (int j = 0; j < info_num; j++) { if (str[i] == info[j].ch) { cout << info[j].code; fout << info[j].code; } } } cout << endl; cout << "以上编码结果已保存到文件'CodeFile.txt'中" << endl; } } void Decoding() { string str; ifstream fin("CodeFile.txt"); fin >> str; ofstream fout("TextFile.txt"); Node* cur = root; int i=0; while (i <= str.length()) { if (cur->Lchild == NULL && cur->Rchild == NULL) { cout << cur->ch; fout << cur->ch; cur = root; } if (str[i] == '0') cur = cur->Lchild; if (str[i] == '1') cur = cur->Rchild; i++; } cout << endl; cout<< "以上译码结果已保存到文件'TextFile.txt'中" << endl; } int main() { cout << "操作菜单:1.建Huffman树 2.编码 3.译码 0.结束"<<endl; int n; while (cin >> n && n) { switch (n) { case 1:Initial();break; case 2:Encoding(); break; case 3:Decoding();break; default:break; } cout << "操作菜单:1.建Huffman树 2.编码 3.译码 0.结束" << endl; } return 0; }