nyoj 801 Haffman编码

描述
哈弗曼编码大家一定很熟悉吧(不熟悉也没关系,自己查去。。。)。现在给你一串字符以及它们所对应的权值,让你构造哈弗曼树,从而确定每个字符的哈弗曼编码。当然,这里有一些小规定:

1.规定哈弗曼树的左子树编码为0,右子树编码为1;

2.若两个字符权值相同,则ASCII码值小的字符为左孩子,大的为右孩子;

3.创建的新节点所代表的字符与它的左孩子的字符相同;

4.所有字符为ASCII码表上32-96之间的字符(即“ ”到“`”之间的字符)。

输入
输入包含多组数据(不超过100组)
每组数据第一行一个整数n,表示字符个数。接下来n行,每行有一个字符ch和一个整数weight,表示字符ch所对应的权值,中间用空格隔开。
输入数据保证每组测试数据的字符不会重复。
输出
对于每组测试数据,按照输入顺序输出相应的字符以及它们的哈弗曼编码结果,具体格式见样例。
样例输入
3
a 10
b 5
c 8
4
a 1
b 1
c 1
d 1
样例输出
a:0
b:10
c:11
a:00
b:01
c:10

d:11

#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;

int N;
char str[101];
struct Node
{
    int father,left,right,num;
    char ch,code[101];
    ///结构体优先队列。对每个字符的权值排序
    ///先出权值比较小的,如果权值相等,出字符较小的
    friend bool operator<(Node a,Node b)
    {
        if(a.father>b.father)
            return true;
        if(a.father==b.father&&a.ch>b.ch)
            return true;
        return false;
    }
} tree[200];
bool cmp(Node a,Node b)
{
    return a.num<b.num;
}
void dfs(int t,int i)
{///t表示huffman树的节点个数
    if(t<N)///说明t编号的节点就是叶子节点
    {
        str[i]='\0';///str[q]='\0',表示字符的结尾,便于后面的strcpy()函数
        strcpy(tree[t].code,str);
        return;
    }
    else
    {
          ///递归访问左孩子
            str[i]='0';
            i++;
            dfs(tree[t].left,i);
            i--;

         ///递归访问右孩子
            str[i]='1';
            i++;
            dfs(tree[t].right,i);
            i--;

    }
}
int main()
{
    priority_queue<Node>Q;
    int n;
    while(~scanf("%d",&n))
    {
    if(n==0)
        continue;
    memset(str,0,sizeof(str));
    memset(tree,0,sizeof(tree));
        for(int i=0; i<n; i++)
        {getchar();
            Node node;
            scanf("%c %d",&node.ch,&node.father);
            node.num=i;///叶子节点的编号
            Q.push(node);
        }
        N=n;
        int t=0;
        ///创建huffman树
        ///利用优先队列 每次选择权值最小的两个,然后将其结果在加入优先队列
        /// 将权值最小的两个  ,添加到树中
        while(Q.size()>1)
        {
            Node node1,node2,node3;
            node1=Q.top();
            Q.pop();
            node2=Q.top();
            Q.pop();
            node3.father=node1.father+node2.father;
            node3.ch=node1.ch;
            node3.left=node1.num;
            node3.right=node2.num;
            node3.num=n++;
            tree[t++]=node1;
            tree[t++]=node2;
            Q.push(node3);
        }
        tree[t++]=Q.top();///优先队列里面剩下一个元素,它就是根节点,直接加到树中
         Q.pop();
       sort(tree,tree+t,cmp);///按照num序号排序,最后可以按编号输出,排除非叶子节点
        dfs(t-1,0);
        for(int i=0; i<N; i++)
            printf("%c:%s\n",tree[i].ch,tree[i].code);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值