C语言构造哈夫曼编码

这段代码展示了如何构造哈夫曼树并求解哈夫曼编码。首先定义了哈夫曼树节点和哈夫曼编码结构体,接着通过循环找到最小权重的节点来构建哈夫曼树。然后,通过遍历哈夫曼树生成每个叶子节点的哈夫曼编码,并将其存储在HCode结构体中。最后,程序输出这些哈夫曼编码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先我们定义两个结构体,一个用于定义哈夫曼树的结点,一个用来定义每个叶子结点的哈夫曼编码.

typedef struct
{
    char data;			//结点值
    double weight;			//权重
    int parent;			//父亲结点
    int lchild;			//左孩子结点
    int rchild;			//右孩子结点
} HTNode;				//哈夫曼树的结点类型

typedef struct
{
    char cd[MAXN];			//存放当前结点的哈夫曼码
    int start;			//用来存储当前叶子结点哈夫曼编码的首地址
} HCode;

构造哈夫曼树,传递数组参数.
定义左右结点,并循环从数组里面找到最小和次小结点.

void CreateHTree(HTNode ht[], int n)	//构造哈夫曼树
{
    int i, j, lnode, rnode;
    double min1, min2;
    for (i = 0; i <= 2 * n - 2; i++)		//所有结点的相关域置初值-1
        ht[i].parent = ht[i].lchild = ht[i].rchild = -1;
    for (i = n; i <= 2 * n - 2; i++)		//构造哈夫曼树
    {
        min1 = min2 = 32767; //lnode和rnode为最小权值的两个结点的下标
        lnode = rnode = -1;
        for (j = 0; j <= i - 1; j++)		//在ht[]中找权值最小的两个结点 ht[]就相当于那个二叉树集合
            if (ht[j].parent == -1)	//只在根结点中查找
            {
                if (ht[j].weight < min1)
                {
                    min2 = min1;
                    rnode = lnode;
                    min1 = ht[j].weight;
                    lnode = j;
                }
                else if (ht[j].weight < min2)
                {
                    min2 = ht[j].weight;
                    rnode = j;
                }
            }
        ht[i].weight = ht[lnode].weight + ht[rnode].weight;
        ht[i].lchild = lnode;
        ht[i].rchild = rnode; //ht[i]作为父亲结点
        ht[lnode].parent = i;
        ht[rnode].parent = i; //将选出的那两个最小和次小结点的父亲修改为i.
    }
}
#include<stdio.h>
#define MAXN 101
typedef struct
{
    char data;			//结点值
    double weight;			//权重
    int parent;			//父亲结点
    int lchild;			//左孩子结点
    int rchild;			//右孩子结点
} HTNode;				//哈夫曼树的结点类型

typedef struct
{
    char cd[MAXN];			//存放当前结点的哈夫曼码
    int start;			//用来存储当前叶子结点哈夫曼编码的首地址
} HCode;

void CreateHTree(HTNode ht[], int n)	//构造哈夫曼树
{
    int i, j, lnode, rnode;
    double min1, min2;
    for (i = 0; i <= 2 * n - 2; i++)		//所有结点的相关域置初值-1
        ht[i].parent = ht[i].lchild = ht[i].rchild = -1;
    for (i = n; i <= 2 * n - 2; i++)		//构造哈夫曼树
    {
        min1 = min2 = 32767; //lnode和rnode为最小权值的两个结点的下标
        lnode = rnode = -1;
        for (j = 0; j <= i - 1; j++)		//在ht[]中找权值最小的两个结点 ht[]就相当于那个二叉树集合
            if (ht[j].parent == -1)	//只在根结点中查找
            {
                if (ht[j].weight < min1)
                {
                    min2 = min1;
                    rnode = lnode;
                    min1 = ht[j].weight;
                    lnode = j;
                }
                else if (ht[j].weight < min2)
                {
                    min2 = ht[j].weight;
                    rnode = j;
                }
            }
        ht[i].weight = ht[lnode].weight + ht[rnode].weight;
        ht[i].lchild = lnode;
        ht[i].rchild = rnode; //ht[i]作为父亲结点
        ht[lnode].parent = i;
        ht[rnode].parent = i; //将选出的那两个最小和次小结点的父亲修改为i.
    }
}
void CreateHCode(HTNode ht[], HCode hcd[], int n) //根据哈夫曼树求哈夫曼编码
{
    int i, f, c;
    for (i = 0; i < n; i++)		//产生每个叶子结点的哈夫曼编码
    {
        hcd[i].start = n - 1;	//哈夫曼编码从cd的n-1下标开始放置
        c = i;				//c初值指要产生编码的结点
        f = ht[i].parent;
        while (f != -1)		//循环直到无父亲结点即到达树根结点
        {
            if (ht[f].lchild == c) //当前结点是父亲结点的左孩子结点
                hcd[i].cd[hcd[i].start--] = '0';
            else		//当前结点是父亲结点的右孩子结点
                hcd[i].cd[hcd[i].start--] = '1';
            c = f;
            f = ht[f].parent;	//再对父亲结点进行同样的操作
        }
        hcd[i].start++;	//start指向哈夫曼编码最开始的二进制位
    }
}
void dispHCode(HTNode ht[], HCode hcd[], int n)	//输出哈夫曼编码
{
    int i, j;
    for (i = 0; i < n; i++)
    {
        printf("  %c:", ht[i].data);
        for (j = hcd[i].start; j < n; j++)
            printf("%c", hcd[i].cd[j]);
        printf("\n");
    }
}


int main()
{
    int n = 5;
    HTNode ht[2 * MAXN - 1];
    HCode hcd[MAXN];

    ht[0].data = 'a';
    ht[0].weight = 4;		//为哈夫曼树添加n个叶子结点

    ht[1].data = 'b';
    ht[1].weight = 2;

    ht[2].data = 'c';
    ht[2].weight = 1;

    ht[3].data = 'd';
    ht[3].weight = 7;

    ht[4].data = 'e';
    ht[4].weight = 3;

    CreateHTree(ht, n);				//建立哈夫曼树
    CreateHCode(ht, hcd, n);			//求哈夫曼编码
    printf("产生的哈夫曼编码如下:\n");
    dispHCode(ht, hcd, n);				//输出哈夫曼编码
    getchar();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值