哈弗曼树的编码

1.头文件HuffmanTree.h

#include <malloc.h>
#include <stdio.h>


struct TreeNode 
{
	char data;
	int value;
	TreeNode * leftNode;
	TreeNode * rightNode;
	TreeNode * parentNode;
	char hf01;
};

struct LinkList
{
	TreeNode *tn;
	LinkList * lk_next;//可以考虑使用*TreeNext
};
LinkList * CreateLinkList(TreeNode * tn)
{
	LinkList* l=(LinkList*)malloc(sizeof(LinkList));
	l->tn=tn;
	l->lk_next=NULL;
	return l;
}
LinkList * ConnectLinkList(LinkList * head,LinkList * linkend)
{
	LinkList * p=head;
	if (p==NULL)
	{
		return NULL;
	}
	while (p->lk_next!=NULL)
	{
		p=p->lk_next;
	}
	p->lk_next=linkend;
	return head;
}
LinkList * DeleteLinkElemNode(LinkList * lk_head)
{
	LinkList * head=lk_head->lk_next;
	return head;
}
TreeNode * popElemNode(LinkList * lk_head)
{
	return lk_head->tn;
}
LinkList * InsertLinkElemNode(LinkList * lk_head,TreeNode * t)
{
	LinkList * p=lk_head;
	LinkList * pre=NULL;
	LinkList * temp= CreateLinkList(t);
	if (lk_head==NULL)
	{
		return temp;
	}
	while(p!=NULL){
		if (t->value<=p->tn->value)
		{		
			if (p==lk_head)//插入在开始
			{
				lk_head=temp;
				temp->lk_next=p;
			}
			else{//插入在中间
				temp->lk_next=p;
				pre->lk_next=temp;
			}
			break;
		}
		pre=p;
		p=p->lk_next;
	}
	if (p==NULL)//插入在末尾
	{
		pre->lk_next=temp;
	}
	return lk_head;
}

TreeNode * CreateBiTree(char d,int v)
{
	TreeNode * t=NULL;
	t=(TreeNode*)malloc(sizeof(TreeNode));
	t->data=d;
	t->value=v;
	t->leftNode=NULL;
	t->rightNode=NULL;
	t->hf01='0';
	t->parentNode=NULL;
	return t;
}
TreeNode * CommNewbBiTree(TreeNode * t1,TreeNode * t2)
{
	TreeNode * t=NULL;
	t=(TreeNode*)malloc(sizeof(TreeNode));//要检查是否开辟空间成功,这里没处理
	t->leftNode=t1;
	t->rightNode=t2;
	t->value=t1->value + t2->value;
	t->data=NULL;
	t->parentNode=NULL;
	t->hf01='0';

	t1->hf01='0';
	t2->hf01='1';
	t1->parentNode=t;
	t2->parentNode=t;
	return t;
}

2.源文件

#include "HuffManTree.h"
#include <string.h>

//给定一个字符串,根据字符出现的频率进行哈夫曼编码
//abdsdfdkfdfjkgjkekjrerkekrjerjkrejrelklfdkldf
//asdsfdgweweweew afsdd

struct Letter
{
	char data;
	int num;
	char hfcode[10];//可以装下叶子节点为512,去除最后一个用来放'\0',也可以装下256,ascii表只有180不到,够了。
};

struct Letter l[256];
int letterlen=0;
void TraversBiTree(TreeNode *t)
{
	if (t==NULL)
	{
		return;
	}
	if (t->data!=NULL)
	{
		printf("%c : ",t->data);
		TreeNode * p=t;
		char hfcode[10];
		int i=0;
		if (p->parentNode==NULL)
		{
			hfcode[i++]='0';
		}
		while(p->parentNode!=NULL)
		{
			hfcode[i++]=p->hf01;
			p=p->parentNode;
		}
		hfcode[i]='\0';
		for (int j=0;j<letterlen;j++)
		{
			//在letter中查找与该叶子节点数据相同的
			if (t->data==l[j].data)
			{
				//拷贝hfcode
				int m=0;
				for (int k=i-1;k>=0;k--)
				{
					l[j].hfcode[m++]=hfcode[k];
				}
				l[j].hfcode[m]='\0';
				printf("%s\n",l[j].hfcode);
				break;
			}
		}
	}
	TraversBiTree(t->leftNode);
	TraversBiTree(t->rightNode);	
}

void PrintHuffManCode(char arr[],int len)
{
	for (int i=0;i<len;i++)
	{
		for (int j=0;j<letterlen;j++)
		{
			if (arr[i]==l[j].data)
			{
				printf("%s",l[j].hfcode);
			}
		}
	}
	printf("\n");
}

void HuffManCodeToLetter(char arr[],TreeNode * t)
{
	//这里可以检查权值wpl 如果不相等就不要解码了
	TreeNode * head=t;
	int len=strlen(arr);
	int i=0;
	while(i<len)
	{
		while(t->data==NULL && i<len){
			if (arr[i]=='0')
			{
				t=t->leftNode;
			}
			else
			{
				t=t->rightNode;
			}
			i++;
		}
		printf("%c",t->data);
		t=head;
	}
	
}
int main()
{
	char arr[101];
	int brr[256]={0};
	gets(arr);
	int len=strlen(arr);
	for (int i=0 ;i<len;i++)
	{
		brr[arr[i]]++;
	}
	int k=0;//Letter的长度
	for (int j=0;j<256;j++)
	{
		if (brr[j]!=0)
		{
			l[k].data=j;
			l[k++].num=brr[j];
		}
		
	}
	letterlen=k;
	//对Letter根据出现的次数进行排序
	for (int i=0;i<k-1;i++)
	{
		for (int j=i+1;j<k;j++)
		{
			if (l[i].num>l[j].num)
			{
				Letter tmp=l[i];
				l[i]=l[j];
				l[j]=tmp;
			}
		}
	}

	//把有效数据加入链表
	TreeNode *t_head=CreateBiTree(l[0].data,l[0].num);
	TreeNode * t_p=t_head;
	LinkList* l_head=CreateLinkList(t_head);
	LinkList * l_p=l_head;
	for (int i=1 ;i<k;i++)
	{
		t_p=CreateBiTree(l[i].data,l[i].num);
		l_p=CreateLinkList(t_p);
		l_head=ConnectLinkList(l_head,l_p);
	}
	//链表检查是否正确
	l_p=l_head;
	while(l_p!=NULL){
		printf("link -> %c: %d\n",l_p->tn->data,l_p->tn->value);
		l_p=l_p->lk_next;
	}


	l_p=l_head;
	//构建哈夫曼树
	
	while (l_p->lk_next!=NULL)
	{	
		TreeNode *a1,*b1,*c1;		
		a1=popElemNode(l_p); 
		l_p=DeleteLinkElemNode(l_p);
		b1=popElemNode(l_p);
		l_p=DeleteLinkElemNode(l_p);
		c1= CommNewbBiTree(a1,b1);
		l_p=InsertLinkElemNode(l_p,c1);
	}

	//遍历哈夫曼树,生成哈夫曼编码
	TraversBiTree(l_p->tn);

	//把字符串转换成哈夫曼编码输出
	PrintHuffManCode(arr,len);

	//哈夫曼树解码.
	char zz[]={'1','0','1','1','0','0','0','1','\0'};
	HuffManCodeToLetter(zz,l_p->tn);
	getchar();
	return 0;
}

《哈弗曼树的编码》

    原文作者:哈夫曼树
    原文地址: https://blog.csdn.net/qiumin333/article/details/52718738
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞