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

  1. C++哈弗曼编码

    // haffman.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> using name ...

  2. HDU2527:Safe Or Unsafe(哈弗曼树)

    Problem Description Javac++ 一天在看计算机的书籍的时候,看到了一个有趣的东西!每一串字符都可以被编码成一些数字来储存信息,但是不同的编码方式得到的储存空间是不一样的!并且当 ...

  3. K:哈弗曼树

    相关介绍:  树形结构除了应用于查找和排序等操作时能调高效率,它在信息通讯领域也有着广泛的应用.哈弗曼(Huffman)树就是一种在编码技术方面得到广泛应用的二叉树,它同时也是一种最优二叉树. 哈弗曼 ...

  4. SLT 优先队列 哈弗曼树最小带权路径

    与普通的队列不同,普通的队列是先进先出的,而优先队列出队的顺序不是先进先出,而是大(或者小)元素先出队,需要#include <queue> 成员函数 成员函数 作用 empty() 判断 ...

  5. Safe Or Unsafe(hdu2527)哈弗曼VS优先队列

    Safe Or Unsafe Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  6. java实现哈弗曼树

    O(∩_∩)O~~ 概述 我想学过数据结构的小伙伴一定都认识哈弗曼,这位大神发明了大名鼎鼎的“最优二叉树”,为了纪念他呢,我们称之为“哈弗曼树”.哈弗曼树可以用于哈弗曼编码,编码的话学问可就大了,比如 ...

  7. 哈弗曼树的理解和实现(Java)

    哈弗曼树概述 哈弗曼树又称最优树,是一种带权路径长度最短的树,在实际中有广泛的用途.哈弗曼树的定义,涉及路径.路径长度.权等概念.哈弗曼树可以用于哈弗曼编码,用于压缩,用于密码学等. 哈弗曼树的一些定 ...

  8. PKU 1521 Entropy(简单哈弗曼树_水过)

    题目大意:原题链接 给你一个字符串,首先是计算出一个按正常编码的编码长度,其次是计算出一个用霍夫曼编码的编码长度,最后求正常编码的长度除以霍夫曼编码长度的比值,保留一位小数. 解题思路:需要知道 1. ...

  9. POJ 3253 Fence Repair(简单哈弗曼树_水过)

    题目大意:原题链接 锯木板,锯木板的长度就是花费.比如你要锯成长度为8 5 8的木板,最简单的方式是把21的木板割成13,8,花费21,再把13割成5,8,花费13,共计34,当然也可以先割成16,5 ...

随机推荐

  1. C# 关键字 default

    在泛型类和泛型方法中产生的一个问题是,在预先未知以下情况时,如何将默认值分配给参数化类型 T: T 是引用类型还是值类型. 如果 T 为值类型,则它是数值还是结构 http://msdn.micros ...

  2. HTML5 Canvas核心技术—图形、动画与游戏开发.pdf4

    CanvasRenderingContext2D对象中用于平移.旋转坐标系的方法 镜像 scale(1,-1)绘制垂直镜像:scale(-1,1)绘制水平镜像 自定义的坐标变换 transform() ...

  3. Poj 2299 - Ultra-QuickSort 离散化,树状数组,逆序对

    Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 52306   Accepted: 19194 ...

  4. iPhone 6出现后,如何将一份设计稿支持多个尺寸?

    http://mp.weixin.qq.com/s?__biz=MzA4NTQzNTMwOA==&mid=201174413&idx=3&sn=c3fe5b3459bac288 ...

  5. mongDB基本命令和Java操作MongoDB

    上一篇博文<mongoDB安装>我们安装了mongoDB,现在来复习一下它的一些基本命令:mongoDB的bin目录加入到path之后,命令行中输入mongo: 然后我们进入正题 1.查看 ...

  6. div border-radius画圆

    不要指定border-width属性: <html> <style type="text/css"> div{ border-style: solid; b ...

  7. MySql中having字句对组记录进行筛选使用说明

    having字句可以让我们筛选成组后的各种数据 having的用法 having字句可以让我们筛选成组后的各种数据,where字句在聚合前先筛选记录,也就是说作用在group by和having字句前 ...

  8. PAT 1012. The Best Rank

    To evaluate the performance of our first year CS majored students, we consider their grades of three ...

  9. Araxis Merge Professional v2014.4565 特别版 | 文件比较合并

    http://www.ttrar.com/html/AraxisMerge.html Araxis Merge 是一个可视化的文件比较.合并和同步的软件,能够方便的被软件工程师和 web 站点开发者使 ...

  10. Sysinternals Suite实用程序工具包

    Sysinternals Suite是微软出品的一套集成数十个绿色软件的实用程序工具包.就在2014年1月29日(官方日期),迎来了2014新版本 AccessChk为了确保创建安全的环境,Windo ...