哈弗曼编码

哈弗曼编码

问题描述:给定字符集C和每个字符的频率,求关于C的一个最优前缀码。

算法分析:构造最优前缀码的贪心算法就是哈夫曼算法(Huffman)

二元前缀编码存储:二叉树结构,每个字符作为树叶,对应这个字符的前缀码看作根到这片树叶的一条路径,每个结点通向左二子的边记作0,通向右儿子的边记作1.

算法复杂度分析:O(nlogn)

样例:
输入:
3
qwe
3 5 5

输出:
10110

以下是代码:

//
// 算法作业-哈弗曼编码.cpp
// LOY
//
// Created by pro on 16/5/24.
// Copyright (c) 2016年 loy. All rights reserved.
//

#include <stdio.h>
#include <iostream>
#include <string>
#include <queue>
using namespace std;
struct node
{
    int f;   //频率
    int pos;   //记录是第几个字母
    int no;  //记录该节点编号
    int l,r;  //记录左右结点的no
    friend bool operator> (const node a, const node b)
    {
        return a.f > b.f;
    }
};
node tree[1005];  //存储节点
priority_queue<node, vector<node>, greater<node> >q;
node init(int f,int pos,int no,int l,int r)
{
    node tmp;
    tmp.f = f; tmp.pos = pos; tmp.no = no; tmp.l = l; tmp.r = r;
    return tmp;
}
string ans[1005];  //记录答案
void solve(string s,node head)
{
    if (head.l == 0 && head.r == 0)  //访问到叶子节点
    {
        ans[head.pos] = s;
        return;
    }
    if (head.l != 0)  //存在左结点
    {
        solve(s + "0",tree[head.l]);
    }
    if (head.r != 0)  //存在右节点
    {
        solve(s + "1",tree[head.r]);
    }
}

int main()
{
    int n;
    cin >> n;
    string s;
    cin >> s;   //输入字符串
    for (int i = 0; i < n; i++)
    {
        int num;
        cin >> num;  //输入每个字母的频率
        node tmp = init(num,i,i + 1,0,0);  //创建叶子节点
        tree[i + 1] = tmp;
        q.push(tmp);
    }
    int cnt = n + 1;
    for (int i = 0; i < n - 1; i++)
    {
        node a = q.top(); q.pop();
        node b = q.top(); q.pop();
        node c =  init(a.f + b.f,0,cnt++,a.no,b.no);  //左子树为a,右子树为b
        tree[cnt - 1] = c; //存储每个结点
        q.push(c);
    }
    node head = q.top();
    solve("",head);  //递归得出答案
    for (int i = 0; i < n; i++)
    {
        cout << ans[i];
    }
    cout << endl;
    return 0;
}

你可能感兴趣的:(二叉树,哈弗曼编码)