解读赫夫曼树编码的问题
发布时间:2022-03-13 06:37:26
定义:
结点的带权路径长度为从该结点到树根之间的路径长度与结点上权的乘积。树的带权路径长度为树中所有叶子结点的带权路径长度之和。假设有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;
}


猜你喜欢
- 1 顺序结构顺序结构比较简单,就是代码一行一行的执行,本节之前写的所有代码都是顺序结构。例如:public static void main
- 这里之所以说“浅谈”是因为我这里只是简单的介绍如何使用Visual C#进行图像的读入、保存以及对像素的访问。而不涉及太多的算法。一、读取图
- gradle下载慢问题解决方法下载之后自行安装 ps:就是手动更新。官网地址和gradle各版本下载地址:官网:http://gradle.
- 本文实例讲述了Android编程实现系统重启与关机的方法。分享给大家供大家参考,具体如下:最近在做个东西,巧合碰到了sharedUserId
- 1.使用java.util.Properties类的load()方法示例:Java代码InputStream in = lnew Buffe
- 简单之美,springmvc,mybatis就是一个很好的简单集成方案,能够满足一般的项目需求。闲暇时间把项目配置文件共享出来,供大家参看:
- 现实开发中,我们难免遇到跨域问题,以前笔者只知道jsonp这种解决方式,后面听说spring只要加入@CrossOrigin即可解决跨域问题
- 本问介绍了Collections工具类两种sort()方法,具体如下:一、Collections工具类两种sort()方法格式一: publ
- Java序列化是什么?Java序列化是指把Java对象转换为字节序列的过程,Java反序列化是指把字节序列恢复为Java对象的过程。反序列化
- 还原背景大家都做过b-s架构的应用,也就是基于浏览器的软件应用。现在呢有个场景就是FE端也就是前端工程是前后端分离的,采用主流的前端框架VU
- 我在 android里面 使用html5的 localStorage 为什么存不进去也读不出来呀?网上搜了好多都没效果mainWebView
- Spring Security中也提供了默认的注销配置,在开发时也可以按照自己需求对注销进行个性化定制开启注销 默认开启package co
- 前面学习过过滤器, 但是过滤器是针对servlet的, 用在springmvc和spring boot里面, 功能上, 感觉并不是很好用.那
- 为Repository添加自定义方法一、为某个Repository添加自定义方法1、定义一个接口PersonDao,声明要添加的方法。pub
- 在开发过程中,与用户交互式免不了会用到对话框以实现更好的用户体验,所以掌握几种对话框的实现方法还是非常有必要的。在看具体实例之前先对Aler
- Java * 。具体有如下四步骤:通过实现 InvocationHandler 接口创建自己的调用处理器;通过为 Proxy 类指定 C
- 在 Servlet/Jsp 项目中,如果涉及到系统任务,例如在项目启动阶段要做一些数据初始化操作,这些操作有一个共同的特点,只在项目启动时进
- 今天闲来无事写了一个清内存的小东西,类似360,在桌面上悬浮,点击后清除后台无用程序,清除后台程序是通过调用ActivityManger.k
- 什么是有序性在开发中,我们通常按照从上到下的顺序编写程序指令,并且希望cpu和编译器按照我们预先编写的顺序去执。但往往cpu和编译器为了提高
- 一、内部类的概念在 Java 中,可以将一个类定义在另一个类或者一个方法的内部,前者称为内部类,后者称为外部类。内部类也是封装的一种体现。p