(C++附代码!)哈夫曼编码(贪心算法)

(C++附代码!)哈夫曼编码(贪心算法)

一、问题描述

【问题描述】使用贪心算法求解Huffman编码问题,具体来说就是,根据每个字符的出现频率,
使用最小堆构造最小优先队列,构造出字符的最优二进制表示,即前缀码。在程序开始说明部分,
简要描述使用贪心算法求解Huffman编码问题的算法过程。
【输入形式】在屏幕上输入字符个数和每个字符的频率。
【输出形式】每个字符的Huffman编码。
【样例输入】
6
45 13 12 16 9 5
【样例输出】
a 0
b 101
c 100
d 111
e 1101
f 1100
【样例说明】
输入:字符个数为6,a至f每个字符的频率分别为:45, 13, 12, 16, 9, 5。
输出:每个字符对应的Huffman编码。

二、算法思路分析
 哈夫曼算法以自底向上的方式构造表示最优前缀码的二叉树T。算法以|C|个叶结点开始,执行|C|-1次合并,运算后产生最终所要求的树T。在哈夫曼树中,编码字符集中每个字符c的频率是f©。以f为键值的优先队列Q在用做贪心选择时有效地确定当前要合并的两棵具有最小频率的树。一旦两棵具有最小频率的树合并后,产生一棵新的树,其频率和为合并的两棵树的频率之和,并将新树加入Q。
三、图例说明哈夫曼树
(C++附代码!)哈夫曼编码(贪心算法)_第1张图片

四、上代码!

#include 
#define N 50     //叶子结点数
using namespace std;

char alphabet[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};

typedef struct {
    char data;
    int weight;
    int parent;
    int lchild;
    int rchild;
}HTNode;      //结点定义


typedef struct {
    char cd[N];      //存放赫夫曼编码
    int start;       //开始指针 记录每个字母编码在cd数组里开始的位置
}HCode;     //赫夫曼编码


void CreateHT(HTNode ht[],int n)    //构造n个叶子结点的赫夫曼树
{
    int i,k,lnode,rnode;
    int min1,min2;    //存放最小的两个结点
    for(i = 0; i < 2*n-1; i++)      //将所有结点的双亲指针置为NULL
    {
        ht[i].parent = -1;
        ht[i].lchild = -1;
        ht[i].rchild = -1;
    }

    for(i = n; i < 2*n-1; i++)
    {
        min1 = min2 = 32767;     //每次循环时都将min初始化
        lnode = -1;     //lnode存最小的,rnode存次小的
        rnode = -1;
        for(k = 0; k <= i-1; k++) //遍历现在存在的i个结点
        {
            if(ht[k].parent == -1)   //没有父母结点的才判断
            {
                if(ht[k].weight < min1)
                {
                    min2 = min1;
                    rnode = lnode;   //有比min1还小的,原min1就变成了次小的,赋给min2
                    min1 = ht[k].weight;
                    lnode = k;
                }
                else if(ht[k].weight < min2)
                {
                    min2 = ht[k].weight;
                    rnode = k;
                }
            }
        }
            ht[lnode].parent = i;
            ht[rnode].parent = i;
            ht[i].weight = ht[lnode].weight + ht[rnode].weight;
            ht[i].lchild = lnode;
            ht[i].rchild = rnode;
    }
}


void CreateHCode(HTNode ht[],HCode hcd[],int n)    //构造赫夫曼编码
{
    int i,f,c;
    HCode hc;
    for(i = 0; i < n; i++)
    {
        hc.start = n;
        c = i;
        f = ht[i].parent;
        while (f!= -1)
        {
            if(ht[f].lchild == c)
                hc.cd[hc.start--] = '0';
            else
                hc.cd[hc.start--] = '1';
            c = f;
            f = ht[f].parent;
        }
        hc.start++;
        hcd[i] = hc;
    }
}


void Output(HTNode ht[],HCode hcd[],int n)    //输出赫夫曼编码
{
    int i,j;
    for(i = 0; i < n; i++)
    {
        cout<<ht[i].data<<" ";
        for(j = hcd[i].start; j <= n; j++)
        cout<<hcd[i].cd[j];
        cout<<endl;
    }
}



int main()
{
    int n;
    cin>>n;
    HTNode ht[2*n-1];   //赫夫曼树=>赫夫曼树中总结点数 = 2*叶子结点-1
    HCode hcd[n];   //n个结点的赫夫曼编码

    for(int i = 0; i < n; i++)
    {
        ht[i].data = alphabet[i];
    }
    for(int i = 0; i < n; i++)
    {
        cin>>ht[i].weight;
    }
    CreateHT(ht, n);
    CreateHCode(ht, hcd, n);
    Output(ht, hcd, n);
}

帮助到你请点赞➕收藏➕关注哦~

你可能感兴趣的:(算法,c++,数据结构,贪心算法,huffman,tree)