【哈夫曼树】哈夫曼树的实现以及哈弗曼编码
来源:互联网 发布:飞升真元锻体升级数据 编辑:程序博客网 时间:2024/05/24 01:58
基本概念
1、路径和路径长度
在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径。通路中分支的数目称为路径长度。若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1。
2、结点的权及带权路径长度
若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积。
3、树的带权路径长度
树的带权路径长度规定为所有叶子结点的带权路径长度之和,记为WPL。
4、哈夫曼树
给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。
构造哈夫曼树
Huffman树构造算法:
1、由给定的n个权值{w1,w2,w3,…,wn}构造n棵只有根节点的扩充二叉树森林F={T1,T2,T3,…,Tn},其中每棵扩充二叉树Ti只有一个带权值wi的根节点,左右孩子均为空。
2、重复以下步骤,直到F中只剩下一棵树为止:
a、在F中选取两棵根节点的权值最小的扩充二叉树,作为左右子树构造一棵新的二叉树。将新二叉树的根节点的权值为其左右子树上根节点的权值之和。
b、在F中删除这两棵二叉树;
c、把新的二叉树加入到F中;
这样最后得到哈夫曼树。
结论:从上图可以看出根节点的值为构建哈夫曼树所有节点的值和16 = 7+5+3+1
取两个值最小的值,可以用堆来实现。
#pragma once#include <iostream>#include <assert.h>#include <queue>#include <vector>template <typename T>struct HuffmanTreeNode{ HuffmanTreeNode(const T &data) : _weight(data) , _pLeft(NULL) , _pRight(NULL) , _pParent(NULL) {} T _weight; HuffmanTreeNode *_pLeft; HuffmanTreeNode *_pRight; HuffmanTreeNode *_pParent;};template <typename T>struct greater{ bool operator()(const T &left, const T &right) { return left->_weight > right->_weight; }};template <typename T>class HuffmanTree{public: HuffmanTree(const T *weight, int size, const T &invalid) : pRoot(NULL) , _invalid(invalid) { assert(NULL != weight && size >= 0); _Create(weight, size); } ~HuffmanTree() { _Destroy(pRoot); } void LevelTraverse() { std::queue<HuffmanTreeNode<T> *> q; if (NULL != pRoot) q.push(pRoot); while (!q.empty()) { HuffmanTreeNode<T> *pCur = q.front(); q.pop(); std::cout << pCur->_weight << " "; if (NULL != pCur->pLeft) q.push(pCur->pLeft); if (NULL != pCur->pRight) q.push(pCur->pRight); } std::cout << std::endl; } HuffmanTreeNode<T> * GetRoot() { return pRoot; }private: void _Destroy(HuffmanTreeNode<T> * &pRoot) { if (NULL != pRoot) { _Destroy(pRoot->_pLeft); _Destroy(pRoot->_pRight); delete pRoot; pRoot = NULL; } } void _Create(const T *weight, int size) { if (0 == size) return; else if (1 == size) { if (*weight != _invalid) pRoot = new HuffmanTreeNode<T>(*weight); } else { std::priority_queue<HuffmanTreeNode<T> *, std::vector<HuffmanTreeNode<T>* >, greater<HuffmanTreeNode<T>*> > heap; for (int i = 0; i < size; ++i) { if (weight[i] != _invalid) { HuffmanTreeNode<T> *tmp = new HuffmanTreeNode<T>(weight[i]); heap.push(tmp); } } HuffmanTreeNode<T> *pLeft, *pRight; while (heap.size() >= 2) { pLeft = heap.top(); heap.pop(); pRight = heap.top(); heap.pop(); HuffmanTreeNode<T> *pParent = new HuffmanTreeNode<T>(pLeft->_weight + pRight->_weight); pParent->_pLeft = pLeft; pParent->_pRight = pRight; pLeft->_pParent = pParent; pRight->_pParent = pParent; heap.push(pParent); } if (!heap.empty()) pRoot = heap.top(); } }private: HuffmanTreeNode<T> *pRoot; T _invalid; //非法值};
哈夫曼编码
统计字符出现的个数,然后进行构建哈夫曼树;
后序遍历哈夫曼树,左0右1,对每个叶子节点
注意:在建立不等长编码时,必须是任何一个字符的编码不能是另一个字符编码的前缀,这样才能保证译码的唯一性。
任何一个字符的huffman编码都不可能是另一个字符的huffman编码的前缀。
- 【哈夫曼树】哈夫曼树的实现以及哈弗曼编码
- 哈夫曼树以及哈夫曼编码的实现
- 哈夫曼树的构造以及编码实现
- 数据结构(15)--哈夫曼树以及哈夫曼编码的实现
- 哈夫曼树的构造以及编码
- 哈夫曼树的创建以及编码
- 哈夫曼树的编码实现
- 哈夫曼树以及哈夫曼编码
- 哈夫曼树以及哈夫曼编码 .
- c++哈夫曼树以及编码
- 哈夫曼树以及编码
- 哈夫曼树以及哈夫曼编码
- 哈夫曼树以及哈夫曼编码
- 哈夫曼树以及哈夫曼编码
- 哈夫曼树以及哈夫曼编码的创建
- 哈夫曼树的建立以及哈夫曼编码
- Base24编码以及解码的实现
- 哈弗曼编码的实现
- 数据的排序及重排序问题(数据变化需要重排)
- 关于Android中HTTP请求中的EOFException解决办法
- Python面试题总结
- JQuery常用内容(更新中)
- DateUtil(java8)
- 【哈夫曼树】哈夫曼树的实现以及哈弗曼编码
- python语法、变量、内置类型、运算符
- oracle一些常见题目
- 用反射创建对象和方法
- Python- GUI(Tkinter)
- 170816 Ubuntu-Nvidia CUDA+Driver+cuDNN installation-Titan Xp
- 红黑树代码
- loadrunner监控linux服务器8min后停止,是什么原因?
- 论OD最原始的用途------找程序BUG