编写一个程序,对单词按出现频度构造一棵哈夫曼树并输出对应的哈夫曼编码。

#include <iostream>
#define N 50
#define M 2*N-1
using namespace std;
//哈夫曼树结点定义
typedef struct
{
    string data;
    int pd;
    double weight;
    int parent;
    int lchild;
    int rchild;
}HTNode;
//哈夫曼编码结点定义
typedef struct
{
    char cd[N];
    int start;
}HCode;
//创建哈夫曼树
void CreateHT(HTNode ht[], int n)
{
    int i, k, lnode, rnode;
    double min1, min2;//min1用于记录较小的那个结点,min2记录较大的那个
    for (i = 0; i < 2 * n - 1; i++)//初始化结点
    {
        ht[i].parent = ht[i].lchild = ht[i].rchild = -1;
    }
    for (i = n; i < 2 * n - 1; i++)//开始构造哈夫曼树
    {
        min1 = min2 = INT_MAX;
        lnode = rnode = -1;//记录可用的最小的两个结点的位置
        for (k = 0; k <= i - 1; k++)//随着过程的进行,会加入两个选用结点构成的新结点,所以判断条件为k<=i-1
        {
            if (ht[k].parent == -1)//可用结点
            {
                if (ht[k].weight < min1)//比最小的那个结点更小
                {
                    min2 = min1; rnode = lnode;//将较大结点换为较小结点
                    min1 = ht[k].weight; lnode = k;//较小结点更新
                }
                else if (ht[k].weight < min2)//只比较大结点小
                {
                    min2 = ht[k].weight; rnode = k;//较大结点更新
                }
            }
        }
        ht[i].weight = ht[lnode].weight + ht[rnode].weight;//产生新节点
        ht[i].lchild = lnode; ht[i].rchild = rnode;//记录新节点的孩子结点
        ht[lnode].parent = i; ht[rnode].parent = i;//记录孩子结点的父亲
    }
}
//求哈夫曼编码
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;//从该节点倒着回到根结点,编码长度最大也不会超过n
        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 DispHCode(HTNode ht[], HCode hcd[], int n)
{
    int i, k;
    int sum = 0, m = 0, j;//sum存储树的带权路径长度,m存储权和,j存储路径长度
    //输出哈夫曼编码
    cout << "单词"<<'\t'<<"频度"<<'\t'<<"哈夫曼编码"<<endl; 
    for (i = 0; i < n; i++)
    {
        j = 0;
        cout << ht[i].data << '\t'<<ht[i].pd<<'\t';
        for (k = hcd[i].start; k <= n; k++)//输出哈夫曼编码
        {
            cout << hcd[i].cd[k];
            j++;//路径长度+1
        }
        m += ht[i].weight;
        sum += ht[i].weight * j;
        cout << endl;
    }
}
int main()
{
    int n = 15, i;
    string str[] = { "The","of","a","to","and","in","that","he","is","at","on","for","His","are","be" };
    int fnum[] = { 1192,677,541,518,462,450,242,195,190,181,174,157,138,124,123 };
    HTNode ht[M];
    HCode hcd[N];
    for (i = 0; i < n; i++)
    {
        ht[i].data = str[i];
        ht[i].pd = fnum[i];
        ht[i].weight = fnum[i];
    }
    CreateHT(ht, n);//创建哈夫曼树
    CreateHCode(ht, hcd, n);//求得哈夫曼编码
    DispHCode(ht, hcd, n);//输出哈夫曼编码
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值