哈弗曼实现(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 ...
随机推荐
- [LeetCode] Subsets I (78) & II (90) 解题思路,即全组合算法
78. Subsets Given a set of distinct integers, nums, return all possible subsets. Note: Elements in a ...
- hdoj 1286 找新朋友【欧拉函数】
找新朋友 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- 激活Navicat?如何注册Navicat?
在注册界面里面输入信息 名:顺便输入 组织:顺便输入 注册码:NAVH-WK6A-DMVK-DKW3
- windows2012 IIS8.5 不能在此路径中使用此配置节
IIS 8.5 不能在此路径中使用此配置节.如果在父级别上锁定了该节,便会出现这种情况.锁定是默认设置的(overrideModeDefault="Deny"),或者是通过包含 o ...
- 更改Sublimetext3的主题文件,改变某些不喜欢的颜色
使用的主题是Monokai(SL),主题很好看,但是注释和内容选中的颜色看起来跟没有一个样,看起来很淡,所以稍微改一下主题文件的颜色.
- 草稿-Hyper-V
Hyper-V Over SMB3.0 为Hyper-v宿主机和故障转移群集做防病毒排除 微软SMB 3.0文件共享协议新特性介绍
- [D3] 4. d3.max
how to use d3.max to normalize your dataset visually within the specific bounds of a variable domain ...
- oracle15 pl/sql 分页
PL/SQL分页 编写分页过程 无返回值的存储过程 古人云:欲速则不达,为了让大家伙比较容易接受分页过程编写,我还是从简单到复杂,循序渐进的给大家讲解.首先是掌握最简单的存储过程,无返回值的存储过程: ...
- js移除最后一个字符,js替换字符串的连接符号,js移除最后一个分隔符号
js移除最后一个字符 js移除最后一个分隔符号 js替换字符串的连接符号 >>>>>>>>>>>>>>>> ...
- winform鼠标滚轮事件
#region 进入窗体时加载 public FormAlarmInfoQuery() { InitializeComponent(); pictureBox1.ImageLocation = &qu ...