数据结构-赫夫曼树

赫夫曼树

  赫夫曼编码是首个试用的编码方案。属于无损压缩的编码方案。在数据通信中,赫夫曼编码可以根据字符出现频率,构造出一种不等长的二进制,使编码后的电文长度最短,且不产生二义性。

树的带权路径长度WPL

  weighteed path length是树中所有节点的带权路径长度之和。WPL 值越小,说明构造出来的二叉树性能越优。赫夫曼树为最优 WPL 二叉树

赫夫曼编码

  1. 定长编码:一种二进制信息的信道编码,类似ASCII编码,一次变换的输入信息位数固定不变。

  2. 变长编码:单个编码的长度不一致,可以根据整体出现频率来调节。

  3. 前缀码:就是没有任何码字是其他码字的前缀。一个优点就是,前缀码可以方便变长编码的组合,不会引起歧义。赫夫曼编码就是最优的前缀码二叉树。

  程序思路:首先根据每个字符出现的次数(权值),创建一个具有优先级的队列。(出现次数越少排在越前,次数越多排在越后)。然后根据赫夫曼树的构造方法,选择两个权值最小的结点的权值和构造一个新结点S,将S按照大小插入队列中。至队列只剩一个元素时(该元素为根结点),赫夫曼树构造完毕。根据遍历赫夫曼树的结果,左子树用0表示,右子树用1表示,为每个叶子结点生成一个表格,表格中的字符串就是存放的编码。遍历至没有左子树和右子树的时候,就加*\0*。最后设计编码过程和解码过程。编码时遍历需要压缩的文件,找到对应的字符,从赫夫曼表中打印出编码。解码时根据赫夫曼编码,遇到0向左子树走,遇到1向右子树走,最后把字符显示出来。

代码片段

 htTree * buildTree(char *inputString)
{
	//整型指针,记录每个ASCII出现频率
	int * probability = int(*)malloc(sizeof(int)*256);
	//初始化
	for(int i=0;i<256;i++)
	{
		probability[i]=0;
	}
	//统计待编码的字符串各个字符出现次数,传入的字符转换为ASCII值,在probability数组中对应位置自加
	for(int j=0;inputString[j]!='\0';j++)
	{
		probability[(unsigned char) inputString[j]]++;
	}
	//pQueue为队列的头指针
	pQueue * huffmanQueue;
	//为队列头指针分配空间
	initPQueue(&huffmanQueue);
	//初始化队列 填充队列
	for(int k=0;k<256;k++)
	{
		if(probability[k]!=0)
		{
			//分配一个树的结点
			htNode *aux = (htNode *)malloc(sizeof(htNode));
			aux->left=NULL;
			aux->right=NULL;
			aux->symbol = (char) k;

			addPQueue(&huffmanQueue,aux,probability[k]);
		}
	}
}








	//addPQueue
	void addPQueue(pQueue **queue,TYPE val,unsigned int priority)
	{
		if((*queue)->size == MAX_SZ)
		{
			printf("\nQueue is full.\n");
			return;
		}
		pQueueNode *aux = (pQueueNode *)malloc(sizeof(pQueueNode));
		aux->priority = priority;
		aux->val= val;
		//如果是空的队列 则不用比较 直接插入
		if((*queue)->size == 0||(*queue)->first == NULL)
		{
			aux->next=NULL;
			(*queue)->first=aux;
			(*queue)->size=1;
			return;
		}
		//如果不是空队列 则比较后再插入 情况一权值小于第一个结点
		else
		{
			if(priority<=(*queue)->first->priority)
			{
				aux->next=(*queue)->first;
				(*queue)->first=aux;
				(*queue)->size++;
				return;
			}
			//情况二 使用迭代比较
			else
			{
				pQueueNode *iterator=(*queue)->first;
				while(iterator->next!=NULL)
				{
					if(priority<=iterator->next->priority)
						{
							aux->next=iterator-next;
						}
				}
			}
		}
	}

	//初始化队列
	#include "queue.h"
	#include <stdio.h>
	#include <stdlib.h>

	void initPQueue(pQueue **queue)
	{
		(*queue)=(pQueue *)malloc(sizeof(pQueue));
		(*queue)->first=NULL:
		(*queue)->size=0;
		return;
	}

未完成

发布了36 篇原创文章 · 获赞 0 · 访问量 611

猜你喜欢

转载自blog.csdn.net/weixin_43199933/article/details/104911416