这篇随笔主要是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. C# 星期相关代码实例

    本文为引用文章 仅作整理自用 原文链接: https://www.cnblogs.com/yxyl/p/9992841.html @网吧看压力大 从周一到周日的顺序,获取排序数值: int i = D ...

  2. SQLSTATE[HY000] [2002] 错误

    http://www.thinkphp.cn/topic/36194.html 使用tp框架 3.2.3 ,在windows上跑的时候没有任何问题,但是部署到linux系统和是哪个,就会报这个错,不知 ...

  3. element el-table 添加分页连接的序号,清除sortable排序

    先看代码: <el-table :data="tableData" style="width: 100%" stripe size="mediu ...

  4. HTTP请求各参数详解

    HTTP Request的Header信息 1.HTTP请求方式 如下表: GET 向Web服务器请求一个文件 POST 向Web服务器发送数据让Web服务器进行处理 PUT 向Web服务器发送数据并 ...

  5. C# 如何引用 WshShell 类

    如果想要创建快捷方式等,很多使用都需要引用 WshShell 类,这个类需要通过 COM 的方法引用 引用 WshShell 不是在一个程序集,而是 Windows Script Host Objec ...

  6. Python3内置函数、各数据类型(int/str/list/dict/set/tuple)的内置方法快速一览表

    Python3内置函数 https://www.runoob.com/python3/python3-built-in-functions.html int https://www.runoob.co ...

  7. Linux USB 的 Urbs

    linux 内核中的 USB 代码和所有的 USB 设备通讯使用称为 urb 的东西( USB request block). 这个请求块用 struct urb 结构描述并且可在 include/l ...

  8. Javascript 防扒站,防止镜像网站

    自己没日没夜敲出来的站,稍微漂亮一点,被人看上了就难逃一扒,扒站是难免的,但不能让他轻轻松松就扒了: 前些天有个朋友做的官网被某不法网站镜像,严重影响到 SEO,当时的解决方法是通过屏蔽目标 IP 来 ...

  9. dotnet Framework 源代码 类库的意思

    本文告诉大家 dotnet framework 的源代码类库的意思 下面列出来 dotnet framework 源代码的各个类库的作用. System System 命名空间包含基本类和基类,这些类 ...

  10. codeforces 11D(状压dp)

    传送门:https://codeforces.com/problemset/problem/11/D 题意: 求n个点m条边的图里面环的个数 题解: 点的范围只有19,很容易想到是状压. dp[sta ...