解读赫夫曼树编码的问题

所属分类: 软件编程 / C#教程 阅读数: 57
收藏 0 赞 0 分享

定义:

  结点的带权路径长度为从该结点到树根之间的路径长度与结点上权的乘积。树的带权路径长度为树中所有叶子结点的带权路径长度之和。假设有n个权值,试构造一棵有n个叶子结点的二叉树,每个叶子结点带权为wi,则其中带权路径长度最小的二叉树称做最优二叉树或赫夫曼树。

 构造赫夫曼树的方法: 

(1)根据给定的n个权值{w1,w2,w3......}构成n棵二叉树的集合F={T1,T2,T3,T4......},其中每棵二叉树Ti中只有一个带权为wi的根结点,其左右子树均空。

(2)在F中选取两棵根结点的权值最小的树作为左右子树构造一棵新的二叉树,且置新的二叉树的根结点的权值为其左、右子树上根结点的权值之和。

(3)在F中删除这两棵树,同时将新得到的二叉树加入F中。

(4)重复(2)和(3),直到F只含一棵树为止。这棵树便是赫夫曼树。

代码实现:

复制代码 代码如下:

#include<iostream>
#include<assert.h>
using namespace std;

struct HuffmanNode
{
    unsigned int weight;
    unsigned int parent,leftChild,rightChild;
    HuffmanNode()
    {
        weight=0;parent=0;leftChild=0;rightChild=0;
    }
};

void Select(const HuffmanNode* & nodelist,const int length,int & a, int &b)
{
    int min=1000000,min2=1000000;
    for(int i=0;i<length;i++)
    {
        if(min>nodelist[i].weight&&nodelist[i].parent==0)
        {
            min=nodelist[i].weight;
            a=i;
        }
    }
    for(int j=0;j<length;j++)
    {
        if(j!=a&&min2>nodelist[j].weight&&nodelist[j].parent==0)
        {
            min2=nodelist[j].weight;
            b=j;
        }
    }
}

char ** HuffmanCoding(const int *w, const int n)
{
    assert(w!=NULL);
    int i,min1,min2;
    int m = 2*n-1;
    HuffmanNode * nodelist = new HuffmanNode[m]();
    for(i=0;i<n;i++)
    {
        nodelist[i].weight=w[i];
        nodelist[i].parent=0;
    }
    for(i=n;i<m;i++)
    {
        Select(nodelist,i,min1,min2);
        nodelist[min1].parent=i;
        nodelist[min2].parent=i;
        nodelist[i].weight=nodelist[min1].weight+nodelist[min2].weight;
        nodelist[i].rightChild=min2;
        nodelist[i].leftChild=min1;
        nodelist[i].parent=0;
    }
    char temp [20];
    char ** code = new char * [n];
    for(i=0;i<n;i++)
    {
        int j=i;
        int index=0;
        while(j!=m-1)
        {
            if(j==nodelist[nodelist[j].parent].leftChild) temp[index++]='0';
            else temp[index++]='1';
            j=nodelist[j].parent;
        }
        temp[index]='\0';
        code[i] = new char[index+1];
        strcpy(code[i],temp);
    }
    delete nodelist;
    return code;
}

int main()
{
    const int size=6;
    char word[size]={'A','B','C','D','E','F'};//编码字符
    int w[size]={4,3,2,1,7,8};//权重
    char ** code;
    code=HuffmanCoding(w,size);
    assert(code!=NULL);
    for(int i=0;i<size;i++)
    {
        cout<<word[i]<<" is coded as "<<code[i]<<endl;
    }
    //注意二级指针的释放问题
    for(int j=0;j<size;j++)
    {
        delete []code[j];
    }
    delete []code;
    return 0;
}

更多精彩内容其他人还在看

C#中Datetimepicker出现问题的解决方法

这篇文章主要给大家介绍了关于C#中Datetimepicker出现问题的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

C# SQLite数据库入门使用说明

这篇文章主要给大家介绍了关于C#中SQLite数据库入门使用的相关资料,文中通过图文以及示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

C#实现批量下载图片到本地示例代码

这篇文章主要给大家介绍了关于C#如何实现批量下载图片到本地的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用c#具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

如何获取C#中方法的执行时间以及其代码注入详解

这篇文章主要给大家介绍了关于如何获取C#中方法的执行时间以及其代码注入的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起看看吧
收藏 0 赞 0 分享

C#中通过LRU实现通用高效的超时连接探测

这篇文章主要介绍了c#中通过LRU实现通用高效的超时连接探测,非常不错,具有一定的参考借鉴价值 ,需要的朋友可以参考下
收藏 0 赞 0 分享

如何使用C#将Tensorflow训练的.pb文件用在生产环境详解

这篇文章主要给大家介绍了关于如何使用C#将Tensorflow训练的.pb文件用在生产环境的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

C#程序启动项的设置方法

这篇文章主要为大家详细介绍了C#程序启动项的设置方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

c#爬虫爬取京东的商品信息

这篇文章主要给大家介绍了关于利用c#爬虫爬取京东商品信息的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们随着小编来一起学习学习吧
收藏 0 赞 0 分享

C#随机数生成字母金字塔

这篇文章主要为大家详细介绍了C#随机数生成字母金字塔,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

WPF实现窗体中的悬浮按钮

这篇文章主要为大家详细介绍了WPF实现窗体中的悬浮按钮,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享
查看更多