码迷,mamicode.com
首页 > 其他好文 > 详细

看数据结构写代码(32) 赫夫曼树编码以及译码

时间:2015-03-31 16:09:19      阅读:177      评论:0      收藏:0      [点我收藏+]

标签:最优二叉树   赫夫曼树   赫夫曼树实现编码以及解码   

杂谈:最近有点慵懒,不好不好。好几天都没写代码,原本准备上星期完结 树 这一章节的。现在 又耽误了。哎。要抓紧时间啊。

下面直接上代码:

可以到我的网盘下载源代码,或者 直接拷贝下面的源代码 运行

网盘地址:点击打开链接

// 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;
}
运行截图:

技术分享

看数据结构写代码(32) 赫夫曼树编码以及译码

标签:最优二叉树   赫夫曼树   赫夫曼树实现编码以及解码   

原文地址:http://blog.csdn.net/fuming0210sc/article/details/44779571

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!