数据结构实验之二叉树六:哈夫曼编码

Problem Description

字符的编码方式有多种,除了大家熟悉的ASCII编码,哈夫曼编码(Huffman Coding)也是一种编码方式,它是可变字长编码。该方法完全依据字符出现概率来构造出平均长度最短的编码,称之为最优编码。哈夫曼编码常被用于数据文件压缩中,其压缩率通常在20%~90%之间。你的任务是对从键盘输入的一个字符串求出它的ASCII编码长度和哈夫曼编码长度的比值。

Input

输入数据有多组,每组数据一行,表示要编码的字符串。

Output

对应字符的ASCII编码长度la,huffman编码长度lh和la/lh的值(保留一位小数),数据之间以空格间隔。

Sample Input

AAAAABCD
THE_CAT_IN_THE_HAT

Sample Output

64 13 4.9
144 51 2.8

尽管有点差别,但还是尽量试着去还原了一颗哈夫曼树来解这道题,希望各位大大多多指教。以下就是代码。

#include <stdio.h>
#include <stdlib.h>
#include <bits/stdc++.h>

using namespace std;

struct treenode
{
    int num;
    struct treenode *ltreenode = NULL;
    struct treenode *rtreenode = NULL;
};

struct treenode *Delete(int n);
void Insert(struct treenode *t1, struct treenode *t2, int n);
struct treenode *buildtree();
int Min(int a, int b, int Size);

struct treenode *root[300]; //将堆用结构题的形式表示
char str[1000000];

int main()
{
    while(gets(str) != NULL)
    {
        int N[305] = {0};
        int len = strlen(str);
        for(int i = 0; i < len; i++)
        {
            N[(int)str[i]]++;
        }
         //因为太会用sort,所以这一块排序缺陷很大
        sort(N, N+300);	  
        for(int i = 0; i < 300; i++)
            root[i] = buildtree();
        int i = 0, j = 0, sum1 = 0, sum2 = 0;
        while(N[i] == 0)
        {
            i++;
        }
        while(N[i])
        {
            sum1 += N[i];
            root[++j]->num = N[i++];
        }
        //
        while(j > 1)
        {
        //取用堆中拥有值最小的树叉
            struct treenode *t1 = Delete(j);
            j--; //这几个地方懒得想了就这样了emm\(o——o)/
            struct treenode *t2 = Delete(j);
            j--;
            sum2 += t1->num+t2->num; //计算权值
       	//再将得到的值的和插入回堆
            Insert(t1, t2, j);
            j++;
        }
        if(sum2 == 0)     //防止出现只有一个值的堆的情况
        {
            sum2 = root[1]->num;
        }
        printf("%d %d %.1lf\n", sum1*8, sum2, 1.0*sum1*8/sum2);
    }

    return 0;
}

void Insert(struct treenode *t1, struct treenode *t2, int n)
{
    struct treenode *p = (struct treenode *)malloc(sizeof(struct treenode));
    p->ltreenode = t1;
    p->rtreenode = t2;
    p->num = t1->num + t2->num;
    int i = n+1;
    while(i != 1 && p->num < root[i/2]->num)
    {
        root[i] = root[i/2];
        i /= 2;
    }
    root[i] = p;
}

int Min(int a, int b, int Size)
{
    if(b <= Size && root[b]->num < root[a]->num)
        return b;
    else
        return a;
}

struct treenode *Delete(int n)
{
    struct treenode *re = root[1];
    struct treenode *p = root[n--];
    int parent = 1, child = Min(2, 3, n);
    while(child <= n && p->num > root[child]->num)
    {
        root[parent] = root[child];
        parent = child;
        child = Min(child*2, child*2+1, n);
    }
    root[parent] = p;
    return re;
}

struct treenode *buildtree()
{
    struct treenode *root = (struct treenode *)malloc(sizeof(struct treenode));
    root->ltreenode = root->rtreenode = NULL;
    return root;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值