哈夫曼编码

压缩软件:

给定一篇文章,只含有英文大小写字母和空格,以.txt格式存储,统计该文件中各种字符的频率,对各字符进行Huffman编码,将该文件翻译成Huffman编码文件,再将Huffman编码文件翻译成源文件。

 

创建结构体数组,数组的每个元素存有字符,频率,父节点下边,左右孩子的下标。假设有n个结点,先统计每个字符出现的频率当做权值,找出两个权值最小的下标,权值的和作为新的下标存在结构体数组中,遍历n-1次,得到哈夫曼树。从叶结点出发,一直找父节点,直至父节点为根(即par = 0),左边为0,右边为1,得到哈夫曼编码;解码 时按位读取,有映射关系直接输出,否则继续向后读取。

#include <bits/stdc++.h>
using namespace std;
map<char, int>M;
map<char, string>M1;
const int N = 500;
char s[N];
struct node
{
    int weight, par, l, r;
    char c;
};

//找两个最小权的下标min1, min2
void select(node *Htree, int m, int &min1, int &min2)
{
    min1 = min2 = 0;
    Htree[0].weight = 1e9;
    for(int i = 1; i <= m; i++)
    {
        if(!Htree[i].par && Htree[i].weight < Htree[min1].weight)
            min1 = i;
    }
    Htree[min1].par = -1;
    for(int i = 1; i <= m; i++)
    {
        if(!Htree[i].par && Htree[i].weight < Htree[min2].weight)
            min2 = i;
    }
}

//创建哈夫曼树
void H_tree(node *Htree, int n)
{
    int min1 = 0, min2 = 0;
    int now = n+1, m = n;//now是新节点的下标,m是寻找的上限
    for(int i = 1; i < n; i++)
    {
        select(Htree, m, min1, min2);//在[1,m]中找两个最小权的下标组成now
        Htree[now].weight = Htree[min1].weight + Htree[min2].weight;
        Htree[now].l = min1, Htree[now].r = min2;
        Htree[min1].par = now, Htree[min2].par = now;
        now++;
        m++;
    }
}

//打印树
//void print(node *t,int next)
//{
//    printf("%d
",t[next].weight);
//    if(t[next].l)
//        print(t, t[next].l);
//    if(t[next].r)
//        print(t, t[next].r);
//}

//进行哈夫曼编码
void encode(node *Htree, int n, int len)
{
    char temp[N];//临时存放某个叶子节点的哈夫曼编码
    int now = N-1;
    //逆序推出哈夫曼编码,左边为0,右边为1
    temp[now] = '