哈夫曼图片压缩及解压
Huffman |
哈夫曼编码 |
compress |
解压 |
//Compress.h
#ifndef COMPRESS_H
#define COMPRESS_H
typedef unsigned char * buffer;
int Compress(const char *pFilename);
unsigned char Str2byte(const char *pBinStr);
int Encode(const char*pFilename, const HuffmanCode pHC,buffer &pBuffer, const int nSize);
struct HEAD
{
char type[4];//文件类型
int length;//原文件长度
int weight[256];//权值数值
};
int WriteFile(const char*pFilename, const HEAD sHead, unsigned char * pBuffer, const int nSize);
int InitHead(const char *pFilename, HEAD &sHead);
int UnCompress(const char*pFilename);
#endif
//Huffman.h
#ifndef HUFFMAN_H
#define HUFFMAN_H
#define OK 1
#define SIZE 256
struct HTNode {
int weight;//权值
int parent;//父节点
int lchild;//左孩子
int rchild;//右孩子
};
typedef HTNode *HuffmanTree;//动态分配数组存储Huffman树
typedef char **HuffmanCode;//动态分配哈夫曼编码表
//void PreorderTraverse(int root, HuffmanTree pHT);
int HuffmanCoding(HuffmanCode &pHC, HuffmanTree &pHT);
int Select(HuffmanTree pHT, int nSize);
void TestHufTree(HuffmanTree pHT);
void TestHufCode(int root, HuffmanTree pHT, HuffmanCode pHC);
void TestHufTreeN(int root, HuffmanTree pHT);
int HfmTree(HuffmanTree &pHT, int *w, int n);
#endif
//huffman.cpp
#include<iostream>
#include<cstring>
#include"huffman.h"
#pragma warning( disable : 4996)
using namespace std;
/*
void PreorderTraverse(int root, HuffmanTree pHT)
{
cout << pHT[root].weight << " ";//访问节点
if (pHT[root].lchild)//左孩子
{
PreorderTraverse(pHT[root].lchild, pHT);
}
if (pHT[root].rchild)//右孩子
{
PreorderTraverse(pHT[root].rchild, pHT);
}
}
*/
int HuffmanCoding(HuffmanCode &pHC, HuffmanTree &pHT)
{
pHC = (HuffmanCode)malloc((SIZE + 1) * sizeof(char*));
//无栈非递归遍历
char cd[SIZE] = { '\0' };//记录访问路径
int cdlen = 0;//记录当前路径长度
for (int i = 1; i < 512; i++)
{
pHT[i].weight = 0;//遍历 Huffman树时用作节点的状态标志
}
int p = 2*SIZE-1;//根节点
while (p != 0)
{
if (pHT[p].weight == 0)//向左
{
pHT[p].weight = 1;
if (pHT[p].lchild != 0)
{
p = pHT[p].lchild;
cd[cdlen++] = '0';
}
else if (pHT[p].rchild == 0)//登记叶子节点的字符编码
{
pHC[p] = (char*)malloc((cdlen+1) * sizeof(char));
cd[cdlen] = '\0';
strcpy(pHC[p], cd);//复制编码
}
}
else if (pHT[p].weight == 1)//向右
{
pHT[p].weight = 2;
if (pHT[p].rchild != 0)//右孩子为叶子节点
{
p = pHT[p].rchild;
cd[cdlen++] = '1';
}
}
else
{
//退回父节点,编码长度减1
pHT[p].weight = 0;
p = pHT[p].parent;
--cdlen;
}
// printf("*");
}
return