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. windwos server 2008下iis7各种操作

    1.发布一个asp程序带access数据库的 默认server 08是安装了iis7的,但是它默认没支持asp这项,这时你可以直接去控制面板--程序和功能--打开或关闭windows功能(双击打开)- ...

  2. usaco 安慰奶牛

    Description 约翰有N个牧场,编号依次为1到N.每个牧场里住着一头奶牛.连接这些牧场的有P条 道路,每条道路都是双向的.第j条道路连接的是牧场Sj和Ej,通行需要Lj的时间.两牧场之 间最多 ...

  3. 升级cocoapods到1.2 beta版本的方法

    最近写Swfit3.0, 要用到一些框架, 然后就用cocoapods嘛, 结果说要cocoapods1.1.0版本才行, 而自己的是cocoapods1.0.1版本的, 所以就想着升级嘛, 结果就遇 ...

  4. js修改编辑器内容、修改iframe子页内容

    $('#question-stem-uploader').on('click','',function(){ //获取编辑器内容(ke-edit-iframe: 编辑器iframe的classm名称) ...

  5. Mysql分表和分区的区别

    一,什么是mysql分表,分区 什么是分表,从表面意思上看呢,就是把一张表分成N多个小表,具体请看mysql分表的3种方法 什么是分区,分区呢就是把一张表的数据分成N多个区块,这些区块可以在同一个磁盘 ...

  6. struts2标签 遍历map集合

    首先我们来构造几个map集合.    假设如下代码 都是在ssh配置环境下搭建好,(至少struts2开发环境搭建好) (1).java 代码          下面的student对象包含的字段为 ...

  7. chromium截图实现

    声明:本blog是我自己写的,假设要转载,请注明:come from blog of niba! chromium终于显示是在ContentView上.但通过硬件加速.渲染合成的网页之前是在surfa ...

  8. Android Socket编程基础

    前些天写了一个Android手机在局域网内利用Wifi进行文件传输的Demo,其中用到了Socket编程,故此总结(盗了网友的一些图和文字).好久好久没来博客园了~~ 1.什么是Socket? soc ...

  9. DNS的查找机制、中文扩展,及其对手机扫描商标名称的支持

    DNS的查找机制.中文扩展.及其对手机扫描商标名称的支持 DNS的查找机制 当DNS查找主机时,它首先在本域里查找,假设找不到则交给更上一级的域查找,直至顶级的域. 因此,假设计算机在北大域名(pku ...

  10. jvisualvm图解

    http://blog.csdn.net/a19881029/article/details/8432368 jvisualvm能干什么:监控内存泄露,跟踪垃圾回收,执行时内存.cpu分析,线程分析. ...