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

来源:互联网 发布:苹果5没有移动3g网络吗 编辑:程序博客网 时间:2024/05/22 04:55

算法: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[n]用来存储符号信息,和建树无关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;}
0 0
原创粉丝点击