数据结构实验二 赫夫曼编码及应用

一、目的与任务
1.目的:掌握赫夫曼(Huffman)树和赫夫曼编码的基本思想和应用。
2.任务:实现文件中数据的加解密与压缩。
二、内容、要求与安排方式
1.实验内容:将硬盘上的一个文本文件进行加密,比较加密文件和原始文件的大小差别;对加密文件进行解密,比较原始文件和解码文件的内容是否一致。
2.输入和输出:
(1)输入:硬盘上给定的原始文件及文件路径。
(2)输出:
硬盘上的加密文件及文件路径;
硬盘上的解码文件及文件路径;
原始文件和解码文件的比对结果。
3.实验要求:
提取原始文件中的数据(包括中文、英文或其他字符),根据数据出现的频率为权重,构建Huffman编码表;
根据Huffman编码表对原始文件进行加密,得到加密文件并保存到硬盘上;
将加密文件进行解密,得到解码文件并保存点硬盘上;
比对原始文件和解码文件的一致性,得出是否一致的结论。

输出文件路径有点懒了。。。

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <map>
#include <fstream>
#include <queue>
#include <algorithm>
#include <windows.h>
using namespace std;

typedef struct Tree *HuffmanTree;

struct point
{
    char c;
    int weight;
    bool leaf;
};
struct Tree
{
    struct point Date;
    Tree *Lt, *Rt;
    void set_date(char c, int weight, bool leaf, HuffmanTree Lt, HuffmanTree Rt)
    {
        this->Date.c = c;
        this->Date.weight = weight;
        this->Date.leaf = leaf;
        this->Lt = Lt;
        this->Rt = Rt;
    }
};
struct cmp
{
    bool operator () (HuffmanTree a, HuffmanTree b)
    {
        return a->Date.weight > b->Date.weight;
    }
};

void in_it();
HuffmanTree CreateHuffmanTree();
void CreateHuffmanTable(HuffmanTree T, string code);
void ShowTable();
void Coding();
void Decoding();


priority_queue<HuffmanTree, vector<HuffmanTree>, cmp> valueQueue;//
map<string, char> codeToValue;//编码对字符的映射
char path[200];

int main()
{
    in_it();
    HuffmanTree Root = (HuffmanTree)malloc(sizeof(struct Tree));
    Root = CreateHuffmanTree();
    CreateHuffmanTable(Root, "");
    ShowTable();
    Coding();
    Decoding();
}

void in_it()
{
    map<char, int> valueToNum;//字符和数量的映射
    printf("输入文件路径\n");
    cin >> path;
    ifstream text(path, ios::in);
    while(!text.eof())
    {
        char ch;
        text.get(ch);
        if(text.fail())
            break;
        cout << ch;
        if(valueToNum.find(ch) == valueToNum.end())
            valueToNum[ch] = 1;
        else
            valueToNum[ch] += 1;
    }
    text.close();
    putchar('\n');
    map<char, int>::iterator i;
    for(i = valueToNum.begin(); i != valueToNum.end(); i++)
    {
        if(i->first == -1)
            continue;
        HuffmanTree leaf = (HuffmanTree)malloc(sizeof(struct Tree));;
        leaf->set_date(i->first, i->second, true, NULL, NULL);
        valueQueue.push(leaf);
    }
}

HuffmanTree CreateHuffmanTree()
{
    HuffmanTree root;
    while(!valueQueue.empty())
    {
        HuffmanTree L = (HuffmanTree)malloc(sizeof(struct Tree));
        L = valueQueue.top();
        valueQueue.pop();
        if(L->Date.c == '\n')
            printf("%s\t%d\n", "\\n", L->Date.weight);
        else if(L->Date.c == ' ')
            printf("%s\t%d\n", "Space", L->Date.weight);
        else
            printf("%c\t%d\n", L->Date.c, L->Date.weight);
        if(!valueQueue.empty())
        {
            HuffmanTree R = (HuffmanTree)malloc(sizeof(struct Tree));
            R = valueQueue.top();
            valueQueue.pop();
            if(R->Date.c == '\n')
                printf("%s\t%d\n", "\\n", R->Date.weight);
            else if(R->Date.c == ' ')
                printf("%s\t%d\n", "Space", R->Date.weight);
            else
                printf("%c\t%d\n", R->Date.c, R->Date.weight);
            root = (HuffmanTree)malloc(sizeof(struct Tree));
            root->set_date('\0', L->Date.weight+R->Date.weight, false, L, R);
            valueQueue.push(root);
        }
        else
        {
            root = L;
            break;
        }
    }
    putchar('\n');
    return root;
}

void CreateHuffmanTable(HuffmanTree T, string code)
{
    if(T->Date.leaf == true)
    {
        codeToValue[code] = T->Date.c;
        return;
    }
    CreateHuffmanTable(T->Lt, code + "0");
    CreateHuffmanTable(T->Rt, code + "1");
    return;
}

void ShowTable()
{
    printf("编       码      表\n");
    ofstream table("table.txt", ios::out);
    map<string, char>::iterator i;
    for(i = codeToValue.begin(); i != codeToValue.end(); i++)
    {
        if(i->second == '\n')
        {
            cout << i->first+'\t'+'\t' << "\\n" << '\n';
            table << i->first+'\t'+'\t' << "\\n" << '\n';
        }
        else if(i->second == ' ')
        {
            cout << i->first+'\t'+'\t' << "Space" << '\n';
            table << i->first+'\t'+'\t' << "Space" << '\n';
        }
        else
        {
            cout << i->first+'\t'+'\t' << i->second << '\n';
            table << i->first+'\t'+'\t' << i->second << '\n';
        }
    }
    printf("%s%s\n", "文件保存在:", "E:\\Code\\Huffman\\table.txt");
    putchar('\n');
}

void Coding()
{
    printf("Coding......\n");
    ifstream text(path, ios::in);
    ofstream coding("coding.txt", ios::out);
    while(!text.eof())
    {
        char ch;
        text.get(ch);
        if(text.fail())
            break;
        //text >> ch;
        map<string, char>::iterator i;
        for(i = codeToValue.begin(); i != codeToValue.end(); i++)
        {
            if(i->second == ch)
            {
                coding << i->first;
                cout << i->first;
                //coding << endl;
                break;
            }
        }
    }
    text.close();
    coding.close();
    putchar('\n');
    printf("%s%s\n\n", "文件保存在:", "E:\\Code\\Huffman\\coding.txt");
}

void Decoding()
{
    printf("DeCoding......\n");
    ifstream coding("coding.txt", ios::in);
    ofstream decoding("decoding.txt", ios::out);
    string tool;
    while(!coding.eof())
    {
        char ch;
        coding >> ch;
        if(coding.fail())
            break;
        tool = tool + ch;
        if(codeToValue.find(tool) != codeToValue.end())
        {
            decoding << codeToValue[tool];
            cout <<codeToValue[tool];
            tool = "";
        }
        //Sleep(1);
    }
    coding.close();
    decoding.close();
    putchar('\n');
    printf("%s%s\n\n", "文件保存在:", "E:\\Code\\Huffman\\decoding.txt");
}

  • 7
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值