哈弗曼实现(C++)
HuffmanCode.h
#ifndef HUFFMANCODE_H
#define HUFFMANCODE_H enum LRSTATUS
{
LEFTCHILD, //左子树
RIGHTCHILD //右子树
}; struct HuffmanCode
{
//哈弗曼编码类
int weight; //权值
int * pPath; //路径指针
int pathLength; //路径长度
HuffmanCode() //默认构造函数
{
weight = ;
pPath = ;
pathLength = ;
}
//HuffmanCode(int n) //初始化路径指针成员
//{
// pPath = new int [n];
//}
//~HuffmanCode() //销毁并释放路径指针成员
//{
// if (0!=pPath)
// {
// delete [] pPath;
// pPath = 0;
// }
//}
}; #endif //HUFFMANCODE_H
HuffmanNode.h
#ifndef HUFFMANNODE_H
#define HUFFMANNODE_H enum NODESTATUS
{
IN_FOREST, //在森林中
OUT_FOREST //不在森林中
}; struct HuffmanNode
{
//哈弗曼节点结构类
int weight; //节点权值
NODESTATUS flag; //是否在森林里的标志:IN_FOREST为在森林中;OUT_FOREST为不在森林中
HuffmanNode * parent; //双亲指针
HuffmanNode * lChild; //左子树指针
HuffmanNode * rChild; //右子树指针 HuffmanNode() //初始化成员数据
{
weight = ;
flag = OUT_FOREST;
parent = ;
lChild = ;
rChild = ;
}
}; #endif //HUFFMANNODE_H
HuffmanTree.h
#ifndef HUFFMANTREE_H
#define HUFFMANTREE_H #include "HuffmanCode.h"
#include "HuffmanNode.h" class HuffmanTree
{
//哈夫曼树类
private:
HuffmanNode * pNode; //哈弗曼节点指针(即哈弗曼树的节点数组)
HuffmanCode * pCode; //哈弗曼编码指针(即哈弗曼树的路径数组)
int * pWeight; //哈弗曼权值指针(即哈弗曼树的权值数组)
int size; //哈弗曼权值数组大小
protected:
public:
HuffmanTree(int * pWeight, int size); //哈夫曼树构造函数
~HuffmanTree(){}; //哈弗曼树析构函数 void CreateHuffmanTree(HuffmanNode ** ppNode); //创建哈弗曼树,使用ppNode返回哈弗曼节点数组
void GetHuffmanCode(HuffmanNode * pNode, HuffmanCode ** ppCode); //获取哈弗曼编码,使用ppCode返回哈弗曼路径数组
}; void FreeHuffmanTree(HuffmanNode ** ppNode); //释放有函数CreateHuffmanTree申请的动态内存
void FreeHuffmanTree(HuffmanCode ** ppCode); //释放有函数GetHuffmanCode申请的动态内存 #endif //HUFFMANTREE_H
HuffmanTree.cpp
#include "HuffmanTree.h"
#include <iostream>
#include <iomanip> //for setw() using namespace std; #define DEBUG #define MAX_VALUE 0x7FFFFFFF
#define WIDTH 12 //************************************
// Method: HuffmanTree
// FullName: HuffmanTree::HuffmanTree
// Access: public
// Returns:
// Qualifier: HuffmanTree类构造函数,使用HuffmanTree类之前必须进行类对象初始化
// Parameter: int * pWeight
// Parameter: int size
//************************************
HuffmanTree::HuffmanTree(int * pWeight, int size)
{
this->pWeight = pWeight;
this->size = size;
} //************************************
// Method: CreateHuffmanTree
// FullName: HuffmanTree::CreateHuffmanTree
// Access: public
// Returns: void
// Qualifier: 创建哈弗曼树,返回指向保存哈弗曼树节点数组的指针
// Parameter: HuffmanNode * * ppNode
//************************************
void HuffmanTree::CreateHuffmanTree(HuffmanNode ** ppNode)
{
_ASSERT(pWeight || ppNode); //判断是否是空指针 int nodeNum = *size-; //哈弗曼树总节点数
if (nodeNum<=)
return ; //出现错误退出函数
pNode = new HuffmanNode [nodeNum];
_ASSERT(pNode);
for (int i= ; i<size ; ++i) //赋初值
{
pNode[i].weight = pWeight[i];
pNode[i].flag = IN_FOREST;
}
int min1 = MAX_VALUE, min2 = MAX_VALUE; //最小值和次小值
int pos1 = -, pos2 = -; //最小值和次小值位置
for (int i= ; i<size ; ++i) //遍历所有节点并且赋值
{
for (int j= ; j<nodeNum ; ++j) //查找最小值和次小值
{
if (pNode[j].flag==IN_FOREST && pNode[j].weight<min1)
{
min2 = min1;
pos2 = pos1;
min1 = pNode[j].weight;
pos1 = j;
}
else if (pNode[j].flag==IN_FOREST && pNode[j].weight<min2)
{
min2 = pNode[j].weight;
pos2 = j;
}
}
if (-!=pos1 && -!=pos2)
{
//生成最小值和次小值的二叉树双亲
pNode[size+i].weight = (pNode[pos1].weight+pNode[pos2].weight);
pNode[size+i].flag = IN_FOREST;
pNode[size+i].lChild = &pNode[pos1];
pNode[size+i].rChild = &pNode[pos2];
pNode[pos1].flag = OUT_FOREST;
pNode[pos1].parent = &pNode[size+i];
pNode[pos2].flag = OUT_FOREST;
pNode[pos2].parent = &pNode[size+i];
#ifdef NODEBUG
cout << "pNode[" << (size+i) << "].weight = " << pNode[size+i].weight << endl;
cout << "pNode[" << (size+i) << "].flag = " << pNode[size+i].flag << endl;
cout << "pNode[" << (size+i) << "].parent = " << pNode[size+i].parent << endl;
cout << "pNode[" << (size+i) << "].lChild = " << pNode[size+i].lChild << endl;
cout << "pNode[" << (size+i) << "].rChild = " << pNode[size+i].rChild << endl;
cout << "pNode[" << (pos1) << "].weight = " << pNode[pos1].weight << endl;
cout << "pNode[" << (pos1) << "].flag = " << pNode[pos1].flag << endl;
cout << "pNode[" << (pos1) << "].parent = " << pNode[pos1].parent << endl;
cout << "pNode[" << (pos1) << "].lChild = " << pNode[pos1].lChild << endl;
cout << "pNode[" << (pos1) << "].rChild = " << pNode[pos1].rChild << endl;
cout << "pNode[" << (pos2) << "].weight = " << pNode[pos2].weight << endl;
cout << "pNode[" << (pos2) << "].flag = " << pNode[pos2].flag << endl;
cout << "pNode[" << (pos2) << "].parent = " << pNode[pos2].parent << endl;
cout << "pNode[" << (pos2) << "].lChild = " << pNode[pos2].lChild << endl;
cout << "pNode[" << (pos2) << "].rChild = " << pNode[pos2].rChild << endl;
#endif //DEBUG
//重置最小值和次小值
min1 = min2 = MAX_VALUE;
//重置最小值和次小值位置
pos1 = pos2 = -;
}
if (i==size-)
{
pNode[size+i-].flag = OUT_FOREST;
}
#ifdef NODEBUG
cout << "node [] = {" << setw(WIDTH) << "weight" << setw(WIDTH) << "flag" << endl;
for (int k= ; k<nodeNum ; ++k)
{
cout << setw() << " ";
cout << setw(WIDTH) << (pNode[k].flag== ? "IN_FOREST" : "OUT_FOREST") << setw(WIDTH) << pNode[k].weight << endl;
}
cout << setw() << "}" << endl;
#endif //DEBUG
}
#ifdef NODEBUG
for (int k= ; k<nodeNum ; ++k)
{
cout << "pNode[" << (k) << "].weight = " << pNode[k].weight << endl;
cout << "pNode[" << (k) << "].flag = " << pNode[k].flag << endl;
cout << "pNode[" << (k) << "].parent = " << pNode[k].parent << endl;
cout << "pNode[" << (k) << "].lChild = " << pNode[k].lChild << endl;
cout << "pNode[" << (k) << "].rChild = " << pNode[k].rChild << endl;
}
#endif //DEBUG
*ppNode = pNode;
} //************************************
// Method: GetHuffmanCode
// FullName: HuffmanTree::GetHuffmanCode
// Access: public
// Returns: void
// Qualifier: 创建哈夫曼编码,返回指向哈弗曼编码数组的指针(注:调用该函数前一定要先使用函数CreateHuffmanTree)
// Parameter: HuffmanNode * pNode
// Parameter: HuffmanCode * * ppCode
//************************************
void HuffmanTree::GetHuffmanCode(HuffmanNode * pNode, HuffmanCode ** ppCode)
{
_ASSERT(pNode || ppCode);
if (size<=)
return ; //终止函数执行
#ifdef NODEBUG
for (int k= ; k<size*- ; ++k)
{
cout << "pNode[" << (k) << "].weight = " << pNode[k].weight << endl;
cout << "pNode[" << (k) << "].flag = " << pNode[k].flag << endl;
cout << "pNode[" << (k) << "].parent = " << pNode[k].parent << endl;
cout << "pNode[" << (k) << "].lChild = " << pNode[k].lChild << endl;
cout << "pNode[" << (k) << "].rChild = " << pNode[k].rChild << endl;
}
#endif //DEBUG pCode = new HuffmanCode [size];
_ASSERT(pCode); for (int i= ; i<size ; ++i) //赋值操作
{
pCode[i].weight = pWeight[i]; //权值赋值
int pCode_Length = ; //临时变量
HuffmanNode * temp = &pNode[i]; //临时变量
while (NULL!=temp->parent)
{
++pCode_Length;
temp = temp->parent;
}
pCode[i].pathLength = pCode_Length; //路径长度赋值
pCode[i].pPath = new int [pCode[i].pathLength]; //路径数组创建
temp = &pNode[i]; //重新复制临时变量
for (int j=pCode_Length- ; j>= ; --j) //路径数组赋值
{
if (NULL!=temp->parent)
{
HuffmanNode * putValue1 = temp->parent->lChild; //DEBUG
HuffmanNode * putValue2 = temp->parent->lChild; //DEBUG
if (temp==temp->parent->lChild)
pCode[i].pPath[j] = LEFTCHILD;
else
pCode[i].pPath[j] = RIGHTCHILD;
temp = temp->parent;
}
}
#ifdef NODEBUG
cout << "code [] = {" << setw(WIDTH) << "weight" << setw(WIDTH) << "pPath" << endl;
cout << setw() << " ";
cout << setw(WIDTH) << pCode[i].weight << ", ";
cout << setw() << " ";
for (int k= ; k<pCode_Length ; ++k)
cout << pCode[i].pPath[k] << ",";
cout << endl;
#endif //DEBUG
}
#ifdef NODEBUG
for (int k= ; k<size*- ; ++k)
{
cout << "pNode[" << (k) << "].weight = " << pNode[k].weight << endl;
cout << "pNode[" << (k) << "].flag = " << pNode[k].flag << endl;
cout << "pNode[" << (k) << "].parent = " << pNode[k].parent << endl;
cout << "pNode[" << (k) << "].lChild = " << pNode[k].lChild << endl;
cout << "pNode[" << (k) << "].rChild = " << pNode[k].rChild << endl;
}
#endif //DEBUG
*ppCode = pCode;
} //************************************
// Method: FreeHuffmanTree
// FullName: FreeHuffmanTree
// Access: public
// Returns: void
// Qualifier: 销毁由函数CreateHuffmanTree申请的对象
// Parameter: HuffmanNode * * ppNode
//************************************
void FreeHuffmanTree(HuffmanNode ** ppNode)
{
if (NULL!=ppNode && NULL!=*ppNode)
{
delete [] *ppNode;
*ppNode = NULL;
}
} //************************************
// Method: FreeHuffmanTree
// FullName: FreeHuffmanTree
// Access: public
// Returns: void
// Qualifier: 销毁由函数GetHuffmanCode申请的内存
// Parameter: HuffmanCode * * ppCode
//************************************
void FreeHuffmanTree(HuffmanCode ** ppCode)
{
if (NULL!=ppCode && NULL!=*ppCode)
{
int size = _msize(*ppCode)/sizeof(HuffmanCode);
for (int i= ; i<size ; ++i)
{
if (NULL!=(*ppCode+i)->pPath)
{
delete [] (*ppCode+i)->pPath;
(*ppCode+i)->pPath = NULL;
}
}
delete [] *ppCode;
*ppCode = NULL;
}
}
Main.cpp
#include <iostream>
#include "HuffmanTree.h" using namespace std; #define DEBUG #define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h> #ifndef DBG_NEW
#define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )
#define new DBG_NEW
#endif int main() //测试代码
{
::_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
::_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
::_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT); int weight[] = {, , , , , , };
int size = sizeof(weight)/sizeof(int);
#ifdef DEBUG
cout << "weight [] = {" ;
for (int i= ; i<size ; ++i)
cout << weight[i] << ", " ;
cout << "}" << endl;
#endif //DEBUG
HuffmanTree obj(weight, size);
HuffmanNode * pNode = NULL;
obj.CreateHuffmanTree(&pNode);
HuffmanCode * pCode = NULL;
obj.GetHuffmanCode(pNode, &pCode); FreeHuffmanTree(&pNode);
FreeHuffmanTree(&pCode); return ;
}
以上程序共5个文件:
1.Main.cpp文件主要实现对哈弗曼树、哈弗曼编码的测试,并且使用VS专用内存泄露检测代码进行内存泄露检测;
2.类HuffmanNode主要实现哈弗曼节点结构构造;
3.类HuffmanCode主要实现对哈弗曼树路径的存储;
4.类HuffmanTree主要实现哈弗曼树,并且实现创建哈弗曼树,创建哈弗曼编码;
5.使用宏#define DEBUG来对哈弗曼类代码中间结果进行验证。
哈弗曼实现(C++)的更多相关文章
- C++哈弗曼编码
// haffman.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> using name ...
- HDU2527:Safe Or Unsafe(哈弗曼树)
Problem Description Javac++ 一天在看计算机的书籍的时候,看到了一个有趣的东西!每一串字符都可以被编码成一些数字来储存信息,但是不同的编码方式得到的储存空间是不一样的!并且当 ...
- K:哈弗曼树
相关介绍: 树形结构除了应用于查找和排序等操作时能调高效率,它在信息通讯领域也有着广泛的应用.哈弗曼(Huffman)树就是一种在编码技术方面得到广泛应用的二叉树,它同时也是一种最优二叉树. 哈弗曼 ...
- SLT 优先队列 哈弗曼树最小带权路径
与普通的队列不同,普通的队列是先进先出的,而优先队列出队的顺序不是先进先出,而是大(或者小)元素先出队,需要#include <queue> 成员函数 成员函数 作用 empty() 判断 ...
- Safe Or Unsafe(hdu2527)哈弗曼VS优先队列
Safe Or Unsafe Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- java实现哈弗曼树
O(∩_∩)O~~ 概述 我想学过数据结构的小伙伴一定都认识哈弗曼,这位大神发明了大名鼎鼎的“最优二叉树”,为了纪念他呢,我们称之为“哈弗曼树”.哈弗曼树可以用于哈弗曼编码,编码的话学问可就大了,比如 ...
- 哈弗曼树的理解和实现(Java)
哈弗曼树概述 哈弗曼树又称最优树,是一种带权路径长度最短的树,在实际中有广泛的用途.哈弗曼树的定义,涉及路径.路径长度.权等概念.哈弗曼树可以用于哈弗曼编码,用于压缩,用于密码学等. 哈弗曼树的一些定 ...
- PKU 1521 Entropy(简单哈弗曼树_水过)
题目大意:原题链接 给你一个字符串,首先是计算出一个按正常编码的编码长度,其次是计算出一个用霍夫曼编码的编码长度,最后求正常编码的长度除以霍夫曼编码长度的比值,保留一位小数. 解题思路:需要知道 1. ...
- POJ 3253 Fence Repair(简单哈弗曼树_水过)
题目大意:原题链接 锯木板,锯木板的长度就是花费.比如你要锯成长度为8 5 8的木板,最简单的方式是把21的木板割成13,8,花费21,再把13割成5,8,花费13,共计34,当然也可以先割成16,5 ...
随机推荐
- 作品第一课----循环改变DIV颜色
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- advanced dom scripting dynamic web design techniques Chapter 2 CREATING YOUR OWN REUSABLE OBJECTS
JavaScript is all about objects. Objects are the foundation of everything, so if you’re unfamiliar w ...
- angularjs开发常见问题-1(持续更新中...)
angularJs中学习中- 1.刷新当前页面数据:$state.reload service.create(data).then(function (newItem) { flash.success ...
- leetcode第一刷_Triangle
非常easy的一道DP,看到空间限制是O(N)的,不要习惯性的以为是要保存每一行的最小值,不难想到是要保存一行其中各个数为路径终点时的和的大小.当算到最后一行时,就是从顶部究竟部以这个底部位置为终点的 ...
- Test Bench基础知识笔记
学的内容多了,好多指令和用法都容易遗忘和混淆,出现这种情况就需要勤记笔记,忘记了多翻阅几次,基本上就能完全记住了. [`timescale 1ns/1ps]前一个1ns表示时延时间,后一个1ps表示时 ...
- [每日一题] 11gOCP 1z0-052 :2013-08-31 数据库的存储结构....................................................A8
转载请注明出处:http://blog.csdn.net/guoyjoe/article/details/10784599 . 正确答案:A 将逻辑存储与物理存储分开是关系数据库范例的必要部分.关系数 ...
- [D3] 3. Scaling Basics
d3.scale.linear() <!DOCTYPE html> <html> <head lang="en"> <meta chars ...
- sift算法c语言实现
前段时间在做三维測量方面的研究.须要得到物体表面三维数据.sift算法是立体匹配中的经典算法.以下是对RobHess的SIFT源码的凝视.部分内容參考网上,在这里向各位大神表示感谢. http://b ...
- Shell变量之自定义变量、环境变量
1:环境变量 环境变量可以帮我们达到很多功能-包括家目录的变换啊.提示字符的显示啊.运行文件搜寻的路径啊等等的那么,既然环境变量有那么多的功能,问一下,目前我的 shell 环境中, 有 ...
- Java基础知识强化之IO流笔记30:字节流4种方式复制mp4并测试效率
1. 需求:把e:\\哥有老婆.mp4 复制到当前项目目录下的copy.mp4中 字节流四种方式复制文件: • 基本字节流一次读写一个字节 • 基本字节流一次读写一个字节数组 • 高效字节流一次读写一 ...