一 哈夫曼树

1.1 基本概念

1.2 算法描述/构造过程

1.3 算法实现

  • 1> 定义存储结构
# define MAXNEGATIVE -9999 //最大负值
# define MAXPOSITIVE 9999 //最大正值 typedef struct HuffmanNode{ // 加 typedef : 避免发生编译错误 " variable or field 'functionName' declared void "
double weight;
int parent, lchild, rchild; //当前节点的双亲结点、左右孩子结点
}*HuffmanTree;
  • 2> 确定最小的两个结点的选择策略(贪婪策略)【次核心】
/**
* 选择权值结点最小的两个结点 s1、s2
*/
void Select(HuffmanTree &HT,int k,int *s1,int *s2){
int min[2]={0, 0}; // 升序排名, 保留 HT中 权重值最小的两个结点的下标
cout<<"Select k:"<<k<<endl;
HT[0].weight = MAXPOSITIVE; // 初始化为最大正值,方便被 初始结点比最小而比下去
for(int i=1;i<=k;i++){
// cout<<"i:"<<i<<"\tweight:"<<HT[i].weight<<"\tparent:"<<HT[i].parent<<"\tparent.weight:"<<HT[HT[i].parent].weight<<endl;
if( HT[i].parent==0 && (HT[i].weight<HT[min[1]].weight)){
if(HT[i].weight<HT[min[0]].weight){ // 小于 最小者
min[1] = min[0]; min[0] = i; cout<<i<<"小于最小者!"<<endl;
} else {
min[1] = i;cout<<i<<"小于次小者!"<<endl; //仅小于 次小者
}
}
}
*s1 = min[0]; // 最小者下标
*s2 = min[1]; // 次小者下标
// cout<<"s1:"<<*s1<<"\ts2:"<<*s2<<endl;
}
  • 3> 创建 Huffman 树【核心】
/**
* 创建 Huffman 树
* n : 初试结点(待编码结点)数
*/
void CreateHuffmanTree(HuffmanTree &HT, int n){
int m = 2*n-1;
HT = new HuffmanNode[m+1]; // 0 位空余
cout<<"Please input initiative node's weight : "<<endl; // 输入结点数据
for(int i=1;i<=n;i++){
cin>>HT[i].weight;
}
for(int k=1;k<=m;k++){ // 初始化所有结点
HT[k].lchild = 0;
HT[k].rchild = 0;
HT[k].parent = 0;
}
for(int j=n+1;j<=m;j++){
int s1,s2;
Select(HT, j-1, &s1, &s2); // 选择权值结点最小的两个结点s1、s2
HT[s1].parent = j; // 合并左右结点
HT[s2].parent = j;
HT[j].lchild = s1;
HT[j].rchild = s2;
HT[j].weight = HT[s1].weight + HT[s2].weight;
}
}
  • 4> 输出哈夫曼树
void OutputHuffmanTree(HuffmanTree &HT, int n){ // 输出 哈夫曼树 中 结点情况
int m = 2*n-1;
for(int i=1;i<=m;i++){
cout<<"<"<<i<<"> weight: "<<HT[i].weight<<"\t"<<"parent: "<<HT[i].parent<<"(weight:"<<HT[HT[i].parent].weight<<")\t";
cout<<"parent.lchild:"<<HT[HT[i].parent].lchild<<"(weight:"<<HT[HT[HT[i].parent].lchild].weight<<")"<<"\t";
cout<<"parent.rchild:"<<HT[HT[i].parent].rchild<<"(weight:"<<HT[HT[HT[i].parent].rchild].weight<<")"<<endl;
}
}
  • 5> 执行:Main函数
int main(){
HuffmanTree HT;
int n;
cout<<"Please input Huffman initiative Node Number:"; // 输入哈夫曼结点初始结点数目 n
int s1, s2;
cin>>n;
CreateHuffmanTree(HT, n);
OutputHuffmanTree(HT, n);
return 0;
}

二 哈夫曼编码

2.1 哈夫曼编码的主要思想

2.2 【前缀编码】

2.3 【哈夫曼编码】

2.4 应用:文件的编码与译码

2.5 哈夫曼编码的算法实现 (根据哈夫曼树,求哈夫曼编码)

  • 1> 定义存储结构
//由于 每个哈夫曼编码是变长编码;因此,使用指针数组来存储每个字符编码串的首地址
typedef char **HuffmanCode; // 动态分配数组,存储哈夫曼编码表 (char 前面不能随意加 struct 关键字)
  • 2> 生成哈夫曼编码(表)(借助于哈夫曼树)
/**
* 根据哈夫曼树,求哈夫曼编码
*/
void CreateHuffmanCodeByHuffmanTree(HuffmanTree HT, HuffmanCode &HC,int n){//从叶子到根,逆向求每个字符的哈夫曼编码
HC = new char *[n+1]; // 分配存储n个字符编码的编码表空间
char *cd = new char [n]; // 分配临时存放每个字符编码的动态数组空间
cd[n-1] = '\0'; // 编码结束符
for(int i=1;i<=n;i++){ // 逐个字符求哈夫曼编码
int start = n-1; // start 初始化指向最后位置 即 编码结束符位置,逆向存储 从叶子到根结点路径的0/1编码
int c = i;
int f = HT[i].parent; // f 指向结点C 的双亲结点
while(f!=0){ // 直到 f 滑动到根节点为止
--start; // 编码表游标向前滑动
if(HT[f].lchild == c){
cd[start] = '0';
} else {
cd[start]= '1';
}
c = f;
f = HT[f].parent; // 逆向, 自(树)底向(树)上
}
HC[i] = new char [n-start]; //为第i个字符编码分配存储空间
strcpy(HC[i], &cd[start]); // 头文件: #include <string.h> 、<stdio.h>
}
delete cd;
}
  • 3> 输出哈夫曼编码(表)
void OutputHuffmanCodes(HuffmanCode &HC,int n){
for(int i=1;i<=n;i++){
cout<<"第"<<i<<"个哈夫曼编码:";
for(int j=0,size=sizeof(HC[i])/sizeof(char);j<size;j++){
cout<<HC[i][j];
}
cout<<endl;
}
}
  • 4> 执行:Main函数
int main(){
HuffmanTree HT;
int n;
cout<<"Please input Huffman initiative Node Number:"; // 输入哈夫曼结点初始结点数目 n
int s1, s2;
cin>>n;
CreateHuffmanTree(HT, n);
OutputHuffmanTree(HT, n); HuffmanCode HC;
CreateHuffmanCodeByHuffmanTree(HT, HC, n);
OutputHuffmanCodes(HC, n);
return 0;
}

三 哈夫曼译(解)码

四 文献

4.1 参考文献

  • 《数据结构(C语言版):严蔚敏/吴伟民》
  • 《算法设计与分析基础([美] Anany Levitin. 潘彦 译)》
    • 贪心算法思想的适用范围

4.2 推荐文献

五 二叉树 补充:红黑树

[C++]哈夫曼树(最优满二叉树) / 哈夫曼编码(贪心算法)的更多相关文章

  1. 树形结构_红黑树:平衡2X 哈夫曼树:最优2X

    红黑树:平衡2X 哈夫曼树:最优2X 红黑树 :TreeSet.TreeMap 哈夫曼树 1. 将w1.w2.…,wn看成是有n 棵树的森林(每棵树仅有一个结点): 2. 在森林中选出根结点的权值最小 ...

  2. 采用C++实现哈夫曼树的创建并输出哈夫曼编码

    一.这篇随笔来自一道信息论的作业题,因为手动编码过于复杂,所以想到了编程解决,原题目如下图所示: 二.源代码如下: #include <iostream> #include <str ...

  3. 【algo&ds】【吐血整理】4.树和二叉树、完全二叉树、满二叉树、二叉查找树、平衡二叉树、堆、哈夫曼树、B树、字典树、红黑树、跳表、散列表

    本博客内容耗时4天整理,如果需要转载,请注明出处,谢谢. 1.树 1.1树的定义 在计算机科学中,树(英语:tree)是一种抽象数据类型(ADT)或是实作这种抽象数据类型的数据结构,用来模拟具有树状结 ...

  4. 哈夫曼树——c++

    哈夫曼树的介绍 Huffman Tree,中文名是哈夫曼树或霍夫曼树,它是最优二叉树. 定义:给定n个权值作为n个叶子结点,构造一棵二叉树,若树的带权路径长度达到最小,则这棵树被称为哈夫曼树. 这个定 ...

  5. 数据结构-哈夫曼树(python实现)

    好,前面我们介绍了一般二叉树.完全二叉树.满二叉树,这篇文章呢,我们要介绍的是哈夫曼树. 哈夫曼树也叫最优二叉树,与哈夫曼树相关的概念还有哈夫曼编码,这两者其实是相同的.哈夫曼编码是哈夫曼在1952年 ...

  6. 数据结构之C语言实现哈夫曼树

    1.基本概念 a.路径和路径长度 若在一棵树中存在着一个结点序列 k1,k2,……,kj, 使得 ki是ki+1 的双亲(1<=i<j),则称此结点序列是从 k1 到 kj 的路径. 从 ...

  7. C++哈夫曼树编码和译码的实现

    一.背景介绍: 给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree).哈夫曼树是带权路径长度最短的树,权值较大的 ...

  8. 哈夫曼树(三)之 Java详解

    前面分别通过C和C++实现了哈夫曼树,本章给出哈夫曼树的java版本. 目录 1. 哈夫曼树的介绍 2. 哈夫曼树的图文解析 3. 哈夫曼树的基本操作 4. 哈夫曼树的完整源码 转载请注明出处:htt ...

  9. 哈夫曼树(二)之 C++详解

    上一章介绍了哈夫曼树的基本概念,并通过C语言实现了哈夫曼树.本章是哈夫曼树的C++实现. 目录 1. 哈夫曼树的介绍 2. 哈夫曼树的图文解析 3. 哈夫曼树的基本操作 4. 哈夫曼树的完整源码 转载 ...

随机推荐

  1. Paper Reading:HyperNet

    论文:HyperNet: Towards Accurate Region Proposal Generation and Joint Object Detection 发表时间:2016 发表作者:( ...

  2. 使用java中的反射获得object对象的属性值

    知识点:使用java中的反射获得object对象的属性值 一:场景 这两天开发代码时,调用别人的后台接口,返回值为Object对象(json形式的),我想获得object中指定的属性值,没有对应的ge ...

  3. 一个ball例程带你进入 Halcon 世界

    * 此例程来自halcon自带例程,请打开 halcon->ctrl+E 打开例程->搜索框中输入ball added by xiejl* ball.hdev: Inspection of ...

  4. 使用 EasyExcel 写Excel数据(表头动态)

    引入 jar 包 <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel&l ...

  5. selenium报错以及各解决方法

    1.driver.findElement(By.name("wd")).sendKeys("selenium"); 报错:The method sendKeys ...

  6. Appium自动化测试教程-自学网-Package与Activity

    Package Package 包.只是在我们的app中这个Package是唯一的,就像你身份证号码一样.在我们做app自动化时,我们就需要知道他的Package,我们知道了Package那么也就知道 ...

  7. AtCoder Beginner Contest 116 C题 【题意:可以在任意区间【L,R】上加1,求通过最少加1次数得到题目给定的区间】】{思维好题}

    C - Grand Garden In a flower bed, there are NN flowers, numbered 1,2,......,N1,2,......,N. Initially ...

  8. 如何实现对ArrayList排序 sort()

    package com.collection; import java.util.ArrayList;import java.util.Collections;import java.util.Com ...

  9. @Async 异步注释 @EnableAsync

    @SpringBootApplication @ComponentScan(basePackages = "com.fddsfsg") //@EnableSwagger2 @Ena ...

  10. @ControllerAdvice与@ControllerAdvice统一处理异常

    https://blog.csdn.net/zzzgd_666/article/details/81544098(copy) 详细看此 所以结合上面我们可以知道,使用@ExceptionHandler ...