这篇随笔主要是Huffman编码,构建哈夫曼树有各种各样的实现方法,如优先队列,数组构成的树等,但本质都是堆。

这里我用数组来存储数据,以堆的思想来构建一个哈弗曼树,并存入vector中,进而实现哈夫曼编码

 

步骤:  1生成哈夫曼树  (取最小权值树和次小权值树生成新树,排列后重新取树,不断重复)

        2编码   (遵循左零右一的原则)

             3解码(是编码的逆向,本文还未实现,日后有机会补充)

data.txt  测试数据:

5
1 2 3 4 5
abcde

结果:

下面贴代码:

 #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实现)的更多相关文章

  1. Huffman树的编码译码

    上个学期做的课程设计,关于Huffman树的编码译码. 要求: 输入Huffman树各个叶结点的字符和权值,建立Huffman树并执行编码操作 输入一行仅由01组成的电文字符串,根据建立的Huffma ...

  2. Huffman树与编码

    带权路径最小的二叉树称为最优二叉树或Huffman(哈夫曼树). Huffman树的构造 将节点的权值存入数组中,由数组开始构造Huffman树.初始化指针数组,指针指向含有权值的孤立节点. b = ...

  3. Huffman树与编码的简单实现

    好久没写代码了,这个是一个朋友问的要C实现,由于不会C,就用JAVA写了个简单的.注释掉的代码属性按照原来朋友发的题里带的参数,发现没什么用就给注释掉了. package other; import ...

  4. Huffman树进行编码和译码

    //编码#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> ...

  5. Huffman树及其编解码

    Huffman树--编解码 介绍:   Huffman树可以根据输入的字符串中某个字符出现的次数来给某个字符设定一个权值,然后可以根据权值的大小给一个给定的字符串编码,或者对一串编码进行解码,可以用于 ...

  6. 构造数列Huffman树总耗费_蓝桥杯

    快排! /** 问题描述 Huffman树在编码中有着广泛的应用.在这里,我们只关心Huffman树的构造过程. 给出一列数{pi}={p0, p1, …, pn-1},用这列数构造Huffman树的 ...

  7. Java蓝桥杯练习题——Huffman树

    Huffman树在编码中有着广泛的应用.在这里,我们只关心Huffman树的构造过程. 给出一列数{pi}={p0, p1, -, pn-1},用这列数构造Huffman树的过程如下: 找到{pi}中 ...

  8. [数据结构与算法]哈夫曼(Huffman)树与哈夫曼编码

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  9. huffman树即Huffma编码的实现

    自己写的Huffman树生成与Huffman编码实现 (实现了核心功能 ,打出了每个字符的huffman编码 其他的懒得实现了,有兴趣的朋友可以自己在我的基础增加功能 ) /* 原创文章 转载请附上原 ...

随机推荐

  1. [转][ASP.NET Core 3框架揭秘] 跨平台开发体验: Windows [下篇]

    由于ASP.NET Core框架在本质上就是由服务器和中间件构建的消息处理管道,所以在它上面构建的应用开发框架都是建立在某种类型的中间件上,整个ASP.NET Core MVC开发框架就是建立在用来实 ...

  2. HTML静态网页--图片热点

  3. 网易大数据平台的Spark技术实践

    网易大数据平台的Spark技术实践 作者 王健宗 网易的实时计算需求 对于大多数的大数据而言,实时性是其所应具备的重要属性,信息的到达和获取应满足实时性的要求,而信息的价值需在其到达那刻展现才能利益最 ...

  4. dos taskkill 命令

    C:\Users\asn\Desktop>taskkill /? TASKKILL [/S system [/U username [/P [password]]]] { [/FI filter ...

  5. vue-cil 打包爬坑(解决)

    1.打包成功不报错,但是打开页面啥都没有?  解决:文件位置:config目录下index.js文件更改assetsPublicPath属性:文件里面有两个assetsPublicPath属性,也就是 ...

  6. Intellij IDEA 如何使用Jrebel热部署

    My Jrebel 已经不再提供免费使用了,或使用破解版Jrebel 或可以移步至 HotSwapAgent,或使用破解的Jrebel. 一个java web项目,在写的过程中我们需要不断调试,如果没 ...

  7. JavaScript DOM查询,原生js实现元素子节点的获取

    在网页网页开发中,经常会需要获取某个网页元素的子元素,然后对其进行事件绑定.或样式修改等行为.这些操作对于jquery来说很容易,但是对于原生js会稍微麻烦一些,这里将介绍四种方法获取元素的子元素(本 ...

  8. 【50.54%】【BZOJ 1879】[Sdoi2009]Bill的挑战

    Time Limit: 4 Sec  Memory Limit: 64 MB Submit: 649  Solved: 328 [Submit][Status][Discuss] Descriptio ...

  9. HDU - 3671 Boonie and Clyde (图的割点)

    As two icons of the Great Depression, Bonnie and Clyde represent the ultimate criminal couple. Stori ...

  10. CodeForces - 375D Tree and Queries (莫队+dfs序+树状数组)

    You have a rooted tree consisting of n vertices. Each vertex of the tree has some color. We will ass ...