Huffman树及其编码(STL array实现)
这篇随笔主要是Huffman编码,构建哈夫曼树有各种各样的实现方法,如优先队列,数组构成的树等,但本质都是堆。
这里我用数组来存储数据,以堆的思想来构建一个哈弗曼树,并存入vector中,进而实现哈夫曼编码
步骤: 1生成哈夫曼树 (取最小权值树和次小权值树生成新树,排列后重新取树,不断重复)
2编码 (遵循左零右一的原则)
3解码(是编码的逆向,本文还未实现,日后有机会补充)
data.txt 测试数据:
|
5 |
结果:

下面贴代码:
#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <array> using namespace std; #define ARR_SIZE 100 //缓冲区大小 typedef struct Tree
{
int freq;
char key = '\0';
Tree *left, *right;
Tree()
{
freq = ;
key = '\0';
left = NULL;
right = NULL;
}
} Tree, *pTree;
union key_or_point
{
char key;
pTree point;
};
enum infor_type
{
key_s,
point_s
};
class infor
{
public:
int freq;//权值
key_or_point kp;//记录键值或者 新生成的树的地址
infor_type type;// 联合体key_or_point的类型由infor_type标志
infor()
{
freq = ;
kp.key = NULL;
type = key_s;
}
}; array<infor, ARR_SIZE> arr;//用来读取要处理的数据
vector<pTree> trees; //所有生成的树都放在vector里面 int num; //要处理的数据个数 bool cmp(infor a, infor b)
{
return a.freq > b.freq;
} void Huffman()
{
//找出最小权值和次小权值
sort(&arr[], &arr[num], cmp);
int cal = num - ;
while (cal > )
{ pTree pta = new Tree();
vector<pTree>::iterator it; pTree ptl = new Tree();
ptl->freq = arr[cal].freq;
// pt all 的左子树
if (arr[cal].type == point_s)
{
pta->left = arr[cal].kp.point;//如果存放的是地址,那么该树已入vector
//无需重复操作
}
else
{
ptl->key = arr[cal].kp.key;
trees.push_back(ptl);
it = trees.end() - ;
pta->left = *it;
} pTree ptr = new Tree();
ptr->freq = arr[cal - ].freq;
// pt all 的右子树
if (arr[cal - ].type == point_s)
{
pta->right = arr[cal - ].kp.point; //如果存放的是地址,那么该树已入vector
//无需重复操作
}
else
{
ptr->key = arr[cal - ].kp.key;
trees.push_back(ptr);
it = trees.end() - ;
pta->right = *it;
} pta->freq = arr[cal].freq + arr[cal - ].freq;
trees.push_back(pta);//pt all 本树 it = trees.end() - ;
arr[cal - ].kp.point = *it;
arr[cal - ].type = point_s;//保存新生成树的地址 arr[cal - ].freq = arr[cal - ].freq + arr[cal ].freq;
//最小权值的树和次权值的树组成新树后,放回原数组
//新树的key_or_point此时类型变为point_s指针指向vector存放的位置 //第一次循环会有三棵树入vector,重新排列后,新树无需重复入vector
cal--;
sort(&arr[], &arr[cal + ], cmp); } } void traversTree(pTree pt, string st = "")
{
//中序遍历二叉树
//遵循左0右1的原则
if (pt->left == NULL && pt->right == NULL)
{
cout.flags(ios::left);
cout.width();
cout << st.c_str() << " ";
cout << pt->key << endl;
return;
}
if (pt->left != NULL)
{
st += '';
traversTree(pt->left, st);
st.pop_back();//从左边出来后要回退一个字符,避免进入右边时多出一个字符
} if (pt->right != NULL)
{
st += '';
traversTree(pt->right, st);
}
return ;
} void printCode()
{
vector<pTree>::iterator it;
it = trees.end() - ;
pTree pt = *it; //取出最顶端的树
cout << "print HuffmanCode:" << endl;
traversTree(pt);
}
int main()
{
ifstream filein("data.txt");
cin.rdbuf(filein.rdbuf());//重定向输入
cin >> num;//要处理的数据个数
for (int i = ; i < num; i++)
{
cin >> arr[i].freq;
}
for (int i = ; i < num; i++)
{
cin >> arr[i].kp.key;
}
Huffman();
printCode();
return ;
}
分析:

这是以上测试数据生成的树的情况。
只有叶子节点表示有效的符号,所以遍历树时返回条件是叶子节点(如果是叶子节点则返回)
总结:
1 编程时用的一些小技巧总结:
1.1 输出调试信息:可以采用如下方式
#ifdef DEBUG
cout调试信息....
#endif
1.2 联合体union需要取得类型时,可以加一个enum来记录和标志uninon的类型
2 编程方法反思:
可以看到源码中用到了两次sort,这是省事的做法了。
目前想到的改进的方法是用二分插入(数据已经排序)
对比起来,我觉得优先队列的方式更易懂且效率更高,但此文也算是一次小探索,值得记录下来
3 感想:
本人入园第一次随笔,如有不足或错误,还望指出。
以上
Huffman树及其编码(STL array实现)的更多相关文章
- Huffman树的编码译码
上个学期做的课程设计,关于Huffman树的编码译码. 要求: 输入Huffman树各个叶结点的字符和权值,建立Huffman树并执行编码操作 输入一行仅由01组成的电文字符串,根据建立的Huffma ...
- Huffman树与编码
带权路径最小的二叉树称为最优二叉树或Huffman(哈夫曼树). Huffman树的构造 将节点的权值存入数组中,由数组开始构造Huffman树.初始化指针数组,指针指向含有权值的孤立节点. b = ...
- Huffman树与编码的简单实现
好久没写代码了,这个是一个朋友问的要C实现,由于不会C,就用JAVA写了个简单的.注释掉的代码属性按照原来朋友发的题里带的参数,发现没什么用就给注释掉了. package other; import ...
- Huffman树进行编码和译码
//编码#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> ...
- Huffman树及其编解码
Huffman树--编解码 介绍: Huffman树可以根据输入的字符串中某个字符出现的次数来给某个字符设定一个权值,然后可以根据权值的大小给一个给定的字符串编码,或者对一串编码进行解码,可以用于 ...
- 构造数列Huffman树总耗费_蓝桥杯
快排! /** 问题描述 Huffman树在编码中有着广泛的应用.在这里,我们只关心Huffman树的构造过程. 给出一列数{pi}={p0, p1, …, pn-1},用这列数构造Huffman树的 ...
- Java蓝桥杯练习题——Huffman树
Huffman树在编码中有着广泛的应用.在这里,我们只关心Huffman树的构造过程. 给出一列数{pi}={p0, p1, -, pn-1},用这列数构造Huffman树的过程如下: 找到{pi}中 ...
- [数据结构与算法]哈夫曼(Huffman)树与哈夫曼编码
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- huffman树即Huffma编码的实现
自己写的Huffman树生成与Huffman编码实现 (实现了核心功能 ,打出了每个字符的huffman编码 其他的懒得实现了,有兴趣的朋友可以自己在我的基础增加功能 ) /* 原创文章 转载请附上原 ...
随机推荐
- js保存图片到手机相册
/保存到相册 function savePic(){ var picurl= $("#picurl").attr("src"); //alert(picurl) ...
- [转]Jquery属性选择器(同时匹配多个条件,与或非)(附样例)
1. 前言 为了处理除了两项不符合条件外的选择,需要用到jquery选择器的多个条件匹配来处理,然后整理了一下相关的与或非的条件及其组合. 作为笔记记录. 2. 代码 1 2 3 4 5 6 7 8 ...
- Codeforces Round #183 (Div. 2)
A. Pythagorean Theorem II 暴力,\(O(n^2)\). B. Calendar 每个日期计算到0年1月1日的天数,相当于转化成前缀和形式. 闰年数计算\[\lfloor\fr ...
- H3C 环路避免机制二:水平分割
- 【7003】&&【a203】合并多项式
Time Limit: 3 second Memory Limit: 2 MB 问题描述 求两个一元多项式的和.输入多项式方式为:多项式项数.每项系数和指数,按指数从大到小的顺序输入.输出多 ...
- document.getElementById()
使用两个for循环取json数据的时候出错: 代码简化如下: for(var a=0;a<3;a++){ for(var b=0;b<3;b++){ document.getElement ...
- H3C FTP其他常用命令
- vue-router再学习
vue路由: 1:动态路由配置 import Vue from 'vue' import Router from 'vue-router' import Index from '@/view/inde ...
- dotnet 通过 WMI 获取系统启动的服务
本文告诉大家如何通过 WMI 获取系统启动的服务 通过 Win32_Service 可以获取系统启动的服务 获取的时候只需要拿Caption和State就可以 var mc = "Win32 ...
- wpf 自定义 ToolTip 模板
示例是在blend中画的,圆角带阴影和倒三角 <Style x:Key="toolTipStyle" TargetType="ToolTip"> & ...