首页 > 代码库 > Huffman树的应用 (数据结构)

Huffman树的应用 (数据结构)

Huffman树的应用

1、先选择一篇文章

2、然后统计字符个数

3、对个数不为0字符的进行编码

4、输出码文

5、进行译码



上机代码:


/*************************************************************************
	> File Name: Huffman树的应用.cpp 
	> Author: zzuspy
	> Mail: zzuspy@qq.com 
	> Created Time: 2014年12月3日 14:30 
 ************************************************************************/

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <stack>
#include <queue>
#define LL long long
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
using namespace std;

typedef struct
{
	int weight;
	int parent, lchild, rchild;
}HTNode, *HuffmanTree;

typedef char * * HuffmanCode;


int s1, s2;
void Select(HuffmanTree &HT, int n)
{
	int i, min;
	for(int i=1; i<=n; i++)
	{
		if(HT[i].parent==0)
		{
			min = i;
			break;
		}
	}
	for(i=1; i<=n; i++)
	{
		if(HT[i].weight<HT[min].weight && HT[i].parent == 0)min = i;
	}
	s1 = min;
	for(int i=1; i<=n; i++)
	{
		if(HT[i].parent==0 && i!=s1)
		{
			min = i;
			break;
		}
	}
	for(int i=1; i<=n; i++)
	{
		if(HT[i].parent == 0 && i!=s1 && HT[i].weight<HT[min].weight && HT[i].weight>=HT[s1].weight) min=i;
	}
	s2 = min;
}



void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n)
{
	if(n<=1) return;
	int m = 2 * n - 1, i;
	HuffmanTree p;
	HT = (HuffmanTree)malloc( (m + 1) * sizeof(HTNode));
	for( p = HT+1, i = 1; i <= n; i++, p++, w++)
	{
		p->weight = *w;
		p->parent = p->lchild = p->rchild = 0;
	}
	for(; i <= m; i++, p++)
	{
		p->weight = p->parent = p->lchild = p->rchild = 0;
	}
	
	//输出这时Huffman树 
	/*for(int i=1; i<=n; i++)
	{
		printf("%d %d %d %d\n", HT[i].weight, HT[i].parent, HT[i].lchild, HT[i].rchild);
	}*/
	
	for(i = n + 1; i<=m; i++)
	{
		Select(HT, i-1);
		//printf("%d %d\n", s1, s2); 
		HT[s1].parent = i; HT[s2].parent = i;
		HT[i].lchild = s1; HT[i].rchild = s2;
		HT[i].weight = HT[s1].weight + HT[s2].weight;
	}

	HC = (HuffmanCode)malloc( ( n + 1 ) * sizeof(char *));
	char *cd = (char *)malloc( n * sizeof(char) );
	cd[n-1] = '\0';
	for(i=1; i<=n; i++)
	{
		int start = n - 1;
		for(int c = i, f = HT[i].parent; f!=0; c=f, f=HT[f].parent)
			if(HT[f].lchild == c)  cd[--start] = '0';
			else cd[--start] = '1';
		HC[i] = (char*)malloc( (n-start) * sizeof(char));
		strcpy(HC[i], &cd[start]);
	}
	free(cd);
}

void mawen(HuffmanCode &HC, char str[])
{
	printf("\n\n");
	FILE *p;
	char c;
	p = fopen("essay","r");
	while((c = fgetc(p))!=EOF)
	{
		for(int i=0; str[i]!='\0'; i++)
		{
			if(str[i] == c)
			{
				printf("%c %s ", c, HC[i+1]);
				break; 
			}
		}
	}
	fclose(p); 
	printf("\n\n");
}

void codetext(char wen[], HuffmanCode &HC, char str[])
{
	int start = 0;
	FILE *p;
	char c;
	p = fopen("essay","r");
	while((c = fgetc(p))!=EOF)
	{
		for(int i=0; str[i]!='\0'; i++)
		{
			if(str[i] == c)
			{
				strcpy(wen+start, HC[i+1]);
				start+=strlen(HC[i+1]);
				break; 
			}
		}
	}
	fclose(p); 
	printf("\n\n");
}
 

void translate(char wen[], int wei[], char str[], HuffmanTree &HT, HuffmanCode &HC,  int elem)
{
	int q = 2 * elem - 1, n=0;
	char *ch;
	ch = (char*)malloc(100*sizeof(char));
	for(int i=0; wen[i]!='\0'; i++)
	{
		if(wen[i] == '0')
		{
			*(ch+n) = '0';
			*(ch+n+1) = '\0';
			n++;
			q = HT[q].lchild;
			if(HT[q].rchild==0 && HT[q].lchild==0)
			{
				int i;
				for(i=0; i<elem; i++)
				{
					if(!strcmp(ch, HC[i+1]))break;
				}
				printf("%c", str[i]);
				q = 2 * elem - 1;
				n = 0;
			}
		}
		else if(wen[i] == '1')
		{
			*(ch+n) = '1';
			*(ch+n+1) = '\0';
			n++;
			q = HT[q].rchild;
			if(HT[q].rchild==0 && HT[q].lchild==0)
			{
				int i;
				for(i=0; i<elem; i++)
				{
					if(!strcmp(ch, HC[i+1]))break;
				}
				printf("%c", str[i]);
				q = 2 * elem - 1;
				n = 0;
			}
		}
	}
}


int wei[128];        //保存字符数大于0的每个字符的数目 (即权值) 
char str[128];      //保存字符数大于0的字符 
int elem = 0;     //统计后字符数大于0的字符的总数 
int statis[128];    //统计文章中各种字符的数目 

char wen[1000010];     //用于保存码文 

int main()
{	
	//打开文件读取字符,再统计每个字符的个数 
	FILE *p;
	char c;
	p = fopen("essay","r");
	while((c = fgetc(p))!=EOF)
	{
		printf("%c", c);      //输出文章 
		statis[c]++;
	}
	fclose(p); 
	
	//输出统计后个数大于0的字符 
	/*for(int i=0; i<128; i++)
	{
		if(statis[i]!=0)
		printf("%c : %d  ", i, statis[i]);
	}*/
	
	//压缩字符,去掉字符数为0的字符 
	for(int i=0; i<128; i++)
	{
		if(statis[i]!=0)
		{
			str[elem] = i;
			wei[elem] = statis[i];
			elem++;
		}
	}
	
	//输出压缩后字符及其个数 
	/*for(int i=0; i<elem; i++)
	{
		printf("%c : %d  ", str[i], wei[i]);
	}*/
	

	//printf("\n%d\n", elem);   //个数大于0的字符总数 

	HuffmanTree HT;
	HuffmanCode HC;	
	//调用Huffman函数 ,将每个字符对应的编码存在HC里,HT为你所建立的Huffman树 
	HuffmanCoding(HT, HC, wei, elem);
	
	//输出构造的Huffman树 
	/*for(int i=1; i<=2*elem-1; i++)
	{
		printf("%d %d %d %d %d\n", i, HT[i].weight, HT[i].parent, HT[i].lchild, HT[i].rchild);
	}*/
	
	//输出个数大于0的字符及其字符编码 
	/*for(int i=1; i<=elem; i++)
	{
		printf("\n%c %s\n", str[i-1], HC[i]);
	}*/
	
	printf("\n\n"); 
	
	//调用码文函数 
	mawen(HC, str);
	
	printf("\n\n"); 
	
	//生成码文
	codetext(wen, HC, str);
	//printf("%s\n", wen); 
	
	//译文
	translate(wen, wei, str, HT, HC, elem); 
	
	
	return 0;
}


Huffman树的应用 (数据结构)