C语言实现Huffman哈夫曼树的创建

目录

一、概念

二、创建哈夫曼树

代码


一、概念

        路径长度:(以图示二叉树为例)

                结点的路径长度:从树根到分支结点的分支数目。A:1,B:2,C:3

                树的路径长度:从树根到每个结点的路径之和。 A:5 B:15

                带权路径长度:所有叶子结点的带权路径之和。

                                        a=1*5+2*15+3*40+4*10+4*30=315

                                        b=1*15+2*40+3*10+3*30=220

                带权路径最小的为哈夫曼树

                哈夫曼编码:左分支赋值为0,右分支赋值1(前提是待编码的树为哈夫曼树)

                        上图为例(该数不是哈夫曼树,只是进行讲解随便找的树)进行编码:

                        A:0

                        B:10

                        C:110

                        D:1110

                        E:1111

                哈夫曼树特点:不唯一  //因为相同的权值放在左边右边都可以,因此树的结果出来不一样

               哈夫曼树不唯一则哈夫曼编码也不唯一  //哈夫曼编码是根据哈夫曼树来的,树不一样自然编码也不同


二、创建哈夫曼树

思路:权值大的往上面放、权值小的往下面放  

哈夫曼树创建过程:

举例:A5 E10 B15 D30 C40

1.先选出两个最小的叶子节点。先构建一个二叉树,生成一个根N1。

2.在所有数据中,除了选择过的叶子节点(A5,E10),加上新生成的根(15)中,比较大小,再选出最小的。也就是在原有数据中用N1替代A和E。

重复上述步骤,直到所有的数据都被选择过,此时哈夫曼树被创建出来

代码

//创建哈夫曼树
//不先创建根,从下往上走的,根是最后堆出来的
typedef struct node
{
    int weight;//权值
    int parent;//父节点下标
    int left;//左孩子下标
    int right;//右孩子下标
    int flag;//标记当前节点是否被选择过
}HaffNode;

void CreateHaff(int* weight, int n, HaffNode* haff)
{
    int i, j;
    int min1, min2;
    int min1x, min2x;//最小和次小的下标
    //1.初始化haff数组
    for (i = 0; i < 2 * n - 1; i++)
    {
        //初始化赋权值
        if (i < n)//前n个值是数组传过来的那n个,赋值
        {
            haff[i].weight = weight[i];
        }
        else//其余的赋初值为0
            haff[i].weight = 0;

        haff[i].parent = -1;
        haff[i].flag = 0;
        haff[i].left = -1;
        haff[i].right = -1;
    }
    //2.构建haff,其实就是构建数组元素
    for (int i = 0; i < n - 1; i++) //构建树的次数n-1次
    {
        min1 = min2 = 65535;//65535是假设的一个最大值
        min1x = min2x = 0;
        //查找两个最小值
        for (j = 0; j < n + i; j++) {//j<n+i:每创建一次树,就会多一个新的结点放到数组中,所以每次查找最小的时候多一个
            {//j<n+i:每创建一次树,就会多一个新的结点放到数组中,所以每次查找最小的时候多一个
                //找最小的
                if (haff[j].weight < min1 && haff[j].flag == 0)
                {//是最小值并且还没被选则将其赋值给min1
                    min2 = min1;//先将现有最小值给min2
                    min2x = min1x;
                    min1 = haff[i].weight;
                    min1x = j;
                }
                //找次小的
                else if (haff[j].weight < min2 && haff[j].flag == 0)
                {
                    min2 = haff[i].weight;
                    min2x = j;
                }
            }
            //用最小的和次小的创建一颗树
            haff[n + i].weight = min1 + min2;
            haff[n + i].left = min1x;
            haff[n + i].right = min2x;
            //将最小的和次小的父结点下标修改
            haff[min1x].parent = n + i;
            haff[min2x].parent = n + i;
            //最小的和次小的flag重置,flag=1时说明结点已使用
            haff[min1x].flag = 1;
            haff[min2x].flag = 1;
        }
    }
}
    int main()
    {
        int weight[] = { 5,15,40,30,10 };
        int n = sizeof(weight) / sizeof(weight[0]);
        HaffNode* phaff = (HaffNode*)malloc(sizeof(HaffNode) * (2 * n - 1));//n个节点最终生成2n-1个结点 //new HaffNode[];
        CreateHaff(weight, n, phaff);
        return 0;
    }

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值