哈夫曼树【贪心算法】

哈夫曼树【贪心算法】

介绍具体的节点和树的算法的构造:一棵树有N个节点,所以节点和树的关系是:多对一的关系。
class Node{
/节点属性/
weight;
parent;
lchild;
rchild;
value;
/构造函数初始化/
public Node()
{
weight=0;
parent=-1;
lchild=-1;
rchild=-1;
value=0;
}
/节点赋值/
public Node(weight,parent,lchild,rchild,value)
{
this.weight=weight;
this.parent=parent;
this.lchild=lchild;
this.value=value;
}
}
class Tree{
Node[];
/树的构造/
public Tree(Node[] node)
{
/节点排序/
node//初始节点
sortedNode//排好序后的节点
/构造树节点/
for(int i=0;i<node.size();i++)
{
sortedNode[0];//最小的节点
sortedNode[1];//第二小的节点
/父节点/
n = node.size()+i //父节点索引值
node[n+i].weight = sortedNode[0].weight+sortedNode[1];
node[n+i].lchild = sortedNode[0]; node[n+i].rchild = sortedNode[1];
/临时节点,存储编码/
sortedNode[0].tempCode = 0; sortedNode[1].tempCode =1;
/最终的叶子节点的编码/
//遍历当前节点父节点的父节点
p=node[i].parent;
while(p!=-1)
if(node[p].lchild = i) node[i].Code=+node[p].code;
//最终倒叙输出编码
for(j=node[i].Code.size()-1;j>-1;j–)
{
output(node[i].code);
}
}
}

代码实现【C++】

#include <iostream>

 using namespace std;

#define MAXBIT      100

#define MAXVALUE  10000

#define MAXLEAF     30

#define MAXNODE    MAXLEAF*2 -1

 

typedef struct

{

    int bit[MAXBIT]; //最大的编码字节数组

    int start;       //编码的开始位置,从高位开始

} HCodeType;        /* 编码结构体 */

typedef struct

{

    int weight;

    int parent;

    int lchild;

    int rchild;

    int value;               //节点的实际值,比如说给定节点(A\B\C\D\E),value分别为A,B,C,D,E

} HNodeType;        /* 结点结构体 */

 

/* 构造一颗哈夫曼树 */

void HuffmanTree (HNodeType HuffNode[MAXNODE],  int n)

{

 

    /* i、j: 循环变量,m1、m2:构造哈夫曼树不同过程中两个最小权值结点的权值,

        x1、x2:构造哈夫曼树不同过程中两个最小权值结点在数组中的序号。*/

    int i, j, m1, m2, x1, x2;

    /* 初始化存放哈夫曼树数组 HuffNode[] 中的结点*/

    for (i=0; i<2*n-1; i++)

    {

        HuffNode[i].weight = 0;//权值

        HuffNode[i].parent =-1;

        HuffNode[i].lchild =-1;

        HuffNode[i].rchild =-1;

        HuffNode[i].value=i; //实际值,可根据情况替换为字母 

    } /* end for */

 

    /* 输入 n 个叶子结点的权值 */

    for (i=0; i<n; i++)

    {

        printf ("Please input weight of leaf node %d: \n", i);

        scanf ("%d", &HuffNode[i].weight);

    } /* end for */

 

    /* 循环构造 Huffman 树 */

    for (i=0; i<n-1; i++)

    {

        m1=m2=MAXVALUE;     /* m1、m2中存放两个无父结点且结点权值最小的两个结点 */

        x1=x2=0;

        /* 找出所有结点中权值最小、无父结点的两个结点,并合并之为一颗二叉树 */

        for (j=0; j<n+i; j++)

        {

                     if (HuffNode[j].weight < m1 && HuffNode[j].parent==-1)

                     {

                            m2=m1;

                            x2=x1;

                            m1=HuffNode[j].weight;

                            x1=j;

                     }

                      else if (HuffNode[j].weight < m2 && HuffNode[j].parent==-1)

                     {

                            m2=HuffNode[j].weight;

                            x2=j;

                     }

        } /* end for */

            /* 设置找到的两个子结点 x1、x2 的父结点信息 */

        HuffNode[x1].parent  = n+i;

        HuffNode[x2].parent  = n+i;

        HuffNode[n+i].weight = HuffNode[x1].weight + HuffNode[x2].weight;

        HuffNode[n+i].lchild = x1;

        HuffNode[n+i].rchild = x2;

          printf("%d\n",HuffNode[n+i].weight);

        printf ("x1.weight and x2.weight in round %d: %d, %d\n", i+1, HuffNode[x1].weight, HuffNode[x2].weight);  /* 用于测试 */

        printf ("\n");

    } /* end for */

 

} /* end HuffmanTree */

 

int main(void)

{  

    HNodeType HuffNode[MAXNODE];            /* 定义一个结点结构体数组 */

    HCodeType HuffCode[MAXLEAF],  cd;       /* 定义一个编码结构体数组, 同时定义一个临时变量来存放求解编码时的信息 */

    int i, j, c, p, n;

    char pp[100];

    printf ("Please input n:\n");

    scanf ("%d", &n);

    HuffmanTree (HuffNode, n);

  

   

    for (i=0; i < n; i++)

    {

        cd.start = n-1;

        c = i;

        p = HuffNode[c].parent;

        while (p != -1)   /* 父结点存在 */

        {

            if (HuffNode[p].lchild == c)

                cd.bit[cd.start] = 0;

            else

                cd.bit[cd.start] = 1;

            cd.start--;        /* 求编码的低一位 */

            c=p;                   

            p=HuffNode[c].parent;    /* 设置下一循环条件 */

        } /* end while */

       

        /* 保存求出的每个叶结点的哈夫曼编码和编码的起始位 */

        for (j=cd.start+1; j<n; j++)

        { HuffCode[i].bit[j] = cd.bit[j];}

        HuffCode[i].start = cd.start;

    } /* end for */

   

    /* 输出已保存好的所有存在编码的哈夫曼编码 */

    for (i=0; i<n; i++)

    {

        printf ("%d 'Huffman code is: ", i);

        for (j=HuffCode[i].start+1; j < n; j++)

        {

            printf ("%d", HuffCode[i].bit[j]);

        }

        printf(" start:%d",HuffCode[i].start);

      

        printf ("\n");

       

    }

    return 0;

}

结果举例

在这里插入图片描述

哈夫曼算法【正确性证明】

1.哈夫曼树的定义
给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman tree)。
2.哈夫曼树的构造
假设有n个权值,则构造出的哈夫曼树有n个叶子结点。 n个权值分别设为 w1,w2,…,wn,则哈夫曼树的构造规则为:
(1) 将w1,w2,…,wn看成是有n 棵树的森林(每棵树仅有一个结点);
(2) 在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和;
(3)从森林中删除选取的两棵树,并将新树加入森林;
(4)重复(2)、(3)步,直到森林中只剩一棵树为止,该树即为我们所求得的哈夫曼树。
哈夫曼构造正确性证明。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力努力在努力(奋斗版)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值