您的位置:首页 > 理论基础 > 数据结构算法

Haffman编码/译码——数据结构作业(二)

2016-01-11 11:45 465 查看
算法:Haffman,DFS

数据结构: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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: