杂谈:最近有点慵懒,不好不好。好几天都没写代码,原本准备上星期完结 树 这一章节的。现在 又耽误了。哎。要抓紧时间啊。
下面直接上代码:
可以到我的网盘下载源代码,或者 直接拷贝下面的源代码 运行
网盘地址:点击打开链接
// HuffmanTree.cpp : 定义控制台应用程序的入口点。
//哈弗曼编码,译码
#include "stdafx.h"
#include <stdlib.h>
#include <cstring>
enum E_State
{
E_State_Error = 0,
E_State_Ok = 1,
};
struct HuffmanNode
{
int weight;//权值
int parent;//父亲节点
int leftChild;//左孩子
int rightChild;//右孩子
};
struct HuffmanCode
{
char srcCode;//原始码
char * dstCode;//赫夫曼编码
};
struct HuffmanTree
{
int len;//字符集的数量
HuffmanCode * codeArray;//编码数组
HuffmanNode * tree;//赫夫曼树..
};
void treeInit(HuffmanTree * tree){
tree->tree = NULL;
tree->codeArray = NULL;
tree->len = 0;
}
void treeDestory(HuffmanTree * tree){
free(tree->tree);//释放赫夫曼树
for (int i = 0; i < tree->len; i++)//释放编码
{
free(tree->codeArray[i].dstCode);
}
free(tree->codeArray);//释放数组
treeInit(tree);
}
//从树里选择两个最小的节点(不包括已经有父亲的)
void selectMin(HuffmanTree tree,int toIndex,int * minIndex1,int * minIndex2){
int times = 0;
int min1,min2;
for (int i = 0; i < toIndex; i++)
{
HuffmanNode node = tree.tree[i];
if (node.parent == 0)
{
if (times == 0)//第一次...
{
min1 = node.weight;
*minIndex1 = i;
}
else if(times == 1)//第二次
{
min2 = node.weight;
*minIndex2 = i;
}
else if(min1 > node.weight || min2 > node.weight)//发现 有比 min1 ,min2 小的权值了.
{
/*min1 > min2 ?
min1 = node.weight,*minIndex1 = i
: min2 = node.weight,*minIndex2 = i;*/
if (min1 > min2)
{
min1 = node.weight;
*minIndex1 = i;
}
else
{
min2 = node.weight;
*minIndex2 = i;
}
}
times++;
}
}
}
//根据 charSet 字符集合 和字符的权值数组 构建赫夫曼树,获取字符编码.
E_State treeCreate(HuffmanTree * tree,char * charSet,int * weightArray){
int len = strlen(charSet);
treeInit(tree);
if (len > 0)
{
int num = 2 * len -1;//赫夫曼树的个数..
tree->tree = (HuffmanNode*)malloc(sizeof(HuffmanNode) * num);
if (tree->tree != NULL)
{
//构建赫夫曼树
tree->codeArray = (HuffmanCode *)malloc(sizeof(HuffmanCode) * len);
tree->len = len;
for (int i = 0; i < len; i++)//初始化.
{
tree->tree[i].parent = 0;
tree->tree[i].leftChild = 0;
tree->tree[i].rightChild = 0;
tree->tree[i].weight = weightArray[i];
//设置赫夫曼编码的源码
tree->codeArray[i].srcCode = charSet[i];
}
for (int i = len; i < num; i++)
{
int minIndex1,minIndex2;//最小权值的两个节点的索引
selectMin(*tree,i,&minIndex1,&minIndex2);//获得索引
tree->tree[minIndex1].parent = i;
tree->tree[minIndex2].parent = i;
tree->tree[i].leftChild = minIndex1;
tree->tree[i].rightChild = minIndex2;
tree->tree[i].weight = tree->tree[minIndex1].weight + tree->tree[minIndex2].weight;
tree->tree[i].parent = 0;
}
//构建赫夫曼编码
char * tempCode = (char *) malloc(sizeof(char) * len);
tempCode[len-1] = '\0';
for (int i = 0; i < len; i++)
{
HuffmanNode node = tree->tree[i];
char * pCode = tempCode+ len-2;
int childIndex = i;
int times = 0;
while (node.parent != 0)
{
HuffmanNode parent = tree->tree[node.parent];
parent.leftChild == childIndex ? *pCode-- = '0' : *pCode-- = '1';
childIndex = node.parent;
node = parent;
times++;
}
tree->codeArray[i].dstCode = (char *) malloc(sizeof(char) * times+1);// 写成times会报错
strcpy(tree->codeArray[i].dstCode,pCode+1);
}
free(tempCode);
return E_State_Ok;
}
}
return E_State_Error;
}
//将 string 转换成 赫夫曼编码
char * findCode(HuffmanTree tree,char data){
for (int i = 0; i < tree.len; i++)
{
if (tree.codeArray[i].srcCode == data)
{
return tree.codeArray[i].dstCode;
}
}
return NULL;
}
void encode(HuffmanTree tree,char * string,char * code){
char * pCode = code;
for (;*string != '\0'; string++)
{
char * dstCode = findCode(tree,*string);
if (dstCode != NULL)
{
for (;*dstCode != '\0'; dstCode++)
{
*pCode++ = *dstCode;
}
}
else
{
printf("------存在非法字符-----------\n");
return;
}
}
*pCode = '\0';
}
//将string 解码
void decode(HuffmanTree tree,char * string,char * code){
int total = 0;
while (*string != '\0')
{
int treeNum = 2*tree.len - 1;
//由 结构可知:赫夫曼树的最后一个节点为根节点
HuffmanNode child = tree.tree[treeNum -1];
int childIndex;
while (child.leftChild != 0 || child.rightChild != 0)
{
if (*string == '0')//左子树
{
childIndex = child.leftChild;
child = tree.tree[childIndex];
}
else if(*string == '1')//右子树.
{
childIndex = child.rightChild;
child = tree.tree[childIndex];
}
string++;
}
code[total++] = tree.codeArray[childIndex].srcCode;
}
code[total] = '\0';
}
void treeTraverse(HuffmanTree tree){
for (int i = 0; i < tree.len; i++)
{
HuffmanCode code = tree.codeArray[i];
printf("%c 的 编码值为:%s\n",code.srcCode,code.dstCode);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
HuffmanTree tree;
int weightArray[] = {18,12,5,10,15,8,13,19};
char * string = "abcdefgh";
treeCreate(&tree,string,weightArray);
printf("%s 的 赫夫曼编码 如下:\n",string);
treeTraverse(tree);
char * encodeBefore = "abcdefghghfdab";//编码前 源码
char afterCode[1000];//编码后
encode(tree,encodeBefore,afterCode);
printf("%s 编码后:%s\n",encodeBefore,afterCode);
char src[1000];
decode(tree,afterCode,src);
printf("%s 解码后:%s\n",afterCode,src);
treeDestory(&tree);
return 0;
}
运行截图: