一步一步写算法(之哈夫曼树 下)

原文:一步一步写算法(之哈夫曼树 下)

【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】

前面说到了哈夫曼树的创建,那下面一个重要的环节就是哈夫曼树的排序问题。但是由于排序的内容是数据结构,因此形式上说,我们需要采用通用数据排序算法,这在我之前的博客里面已经涉及到了(通用算法设计)。所以,我们所要做的就是编写compare和swap两个函数。通用冒泡代码如下所示,

void bubble_sort(void* array[], int length, int (*compare)(void*, void*), void(*swap)(void**, void**))
{
	int outer;
	int inner;

	for(outer = length -1; outer >0; outer --){
		for(inner = 0; inner < outer; inner ++){
			if(compare(array[inner], array[inner + 1]))
				swap(&array[inner], &array[inner + 1]);
		}
	}

	return;
}

compare和swap代码如下所示,

int compare (void* a, void* b)
{
	HUFFMAN_NODE* node1 = (HUFFMAN_NODE*)a;
	HUFFMAN_NODE* node2 = (HUFFMAN_NODE*)b;

	return node1->frequence > node2->frequence ? 1 : 0;
}

void swap(void** a, void** b)
{
	HUFFMAN_NODE* median;
	HUFFMAN_NODE** node1 = (HUFFMAN_NODE**)a;
	HUFFMAN_NODE** node2 = (HUFFMAN_NODE**)b;

	median = *node1;
	*node1 = *node2;
	*node2 = median;
}

有了创建函数和排序函数,那么哈夫曼树就可以创建了,

HUFFMAN_NODE* create_huffman_tree(HUFFMAN_NODE* huffmanNode[], int length)
{
	HUFFMAN_NODE* head = NULL;

	if(NULL == huffmanNode ||  length <= 1)
		return NULL;

	while(length > 1){
		bubble_sort((void**)huffmanNode, length, compare, swap);
		head = create_new_node(‘\0‘,  huffmanNode[0]->frequence + huffmanNode[1]->frequence);
		assert(NULL != head);

		head->left = huffmanNode[0];
		head->right = huffmanNode[1];
		huffmanNode[0]->parent = head;
		huffmanNode[0]->symbol = 1;
		huffmanNode[1]->parent = head;
		huffmanNode[1]->symbol = 0;

		memmove(&huffmanNode[0], &huffmanNode[2], sizeof(HUFFMAN_NODE*) * (length -2));
		huffmanNode[length -2] = head;
		length --;
	}

	return head;
}

上面的代码完整了写出了huffman树的创建过程,那么我们怎么知道符号的编码是多少呢?这其实不难,因为根节点都知道了,我们只要按照自下而上的顺序遍历节点就可以打印出编码,只不过编码是逆序的而已,

void print_code_for_str(HUFFMAN_NODE* pNode, HUFFMAN_NODE* head)
{
	if(NULL == pNode || NULL == head)
		return;

	while(head != pNode){
		printf("%d", pNode->symbol);
		pNode = pNode->parent;
	}

	return;
}

如果对代码本身还有怀疑,可以编译一个测试用例验证一下,

void test()
{
	HUFFMAN_NODE* node1 = NULL;
	HUFFMAN_NODE* node2 = NULL;
	HUFFMAN_NODE* node3 = NULL;
	HUFFMAN_NODE* node4 = NULL;

	HUFFMAN_NODE* test[] = {node1 = create_new_node(‘a‘, 0.1),
		node2 = create_new_node(‘b‘, 0.2),
		node3 = create_new_node(‘c‘, 0.3),
		node4 = create_new_node(‘d‘, 0.4),
	};

	HUFFMAN_NODE* head = create_huffman_tree(test, sizeof(test)/sizeof(HUFFMAN_NODE*));
	print_code_for_str(node1, head);
	print_code_for_str(node2, head);
	print_code_for_str(node3, head);
	print_code_for_str(node4, head);
}

总结:

(1)哈夫曼树不复杂,如果手算可以成功,那么编程应该也没有什么问题

(2)复杂算法都是由小算法搭积木而成的,朋友们应该在基本算法上打下坚实的基础

(3)算法注意复用,这里就用到了原来讲到的通用算法内容

时间: 2024-10-05 12:01:31

一步一步写算法(之哈夫曼树 下)的相关文章

(算法)压缩算法(哈夫曼树)

原文地址:https://www.cnblogs.com/fangdongdemao/p/11185087.html

一步一步写算法(之哈夫曼树 上)

原文:一步一步写算法(之哈夫曼树 上) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 在数据传输的过程当中,我们总是希望用尽可能少的带宽传输更多的数据,哈夫曼就是其中的一种较少带宽传输的方法.哈夫曼的基本思想不复杂,那就是对于出现频率高的数据用短字节表示,对于频率比较低得数据用长字节表示. 比如说,现在有4个数据需要传输,分别为A.B.C.D,所以一般来说,如果此时没有考虑四个数据出现的概率,那么我们完全可以这么分配,平均长度为2, /

数据结构与算法 -- 哈夫曼树思想与创建详解1

PS:什么是哈夫曼树? 给定n个权值作为n个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree).哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近. 计算规则: 假设一组权值,一个权值是一个结点,12  34  2  5  7  ,在这其中找出两个最小的权值,然后组成一个新的权值,再次找出最小的权值结点.如图: 问题: 1:如果程序找出两个最小的权值,把两个权值最小的相加结果再次添加到数组中呢. 2:完成第一步后,又

哈夫曼树(最优二叉树)及哈夫曼算法

哈夫曼树 在一般的数据结构的书中,树的那章后面,著者一般都会介绍一下哈夫曼(HUFFMAN)树和哈夫曼编码.哈夫曼编码是哈夫曼树的一个应用.哈夫曼编码应用广泛,如JPEG中就应用了哈夫曼编码. 首先介绍什么是哈夫曼树.哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树.所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数).树的带权路径长度记为WPL=(W1*L1+W2*L2+W3*L3+...+Wn*Ln),N个权

算法学习-哈夫曼编码(c++实现)

哈夫曼编码 哈夫曼编码虽然简单,但是是一个非常重要的编码方式,它解决了数据存储的一个非常重要的问题:压缩!它的编码方式是最优的,无损的,尤其在图像中使用的非常多.下面讲下它的原理. 编码方式 哈夫曼编码的构造是依据权值的大小来实现的.首先根据权值构造哈夫曼树,然后对哈夫曼树进行逆向遍历,从而找到每个节点的编码方式. 例如: abbcccdddde这个是一个字符串,一共有5个字符.每个字符的权值就是出现的频率,那么a就是1,b权值为2,c的权值为3,d的权值为4,e的权值为1.在普通的编码方式中,

经典算法题每日演练——第十三题 赫夫曼树

原文:经典算法题每日演练--第十三题 赫夫曼树 赫夫曼树又称最优二叉树,也就是带权路径最短的树,对于赫夫曼树,我想大家对它是非常的熟悉,也知道它的应用场景, 但是有没有自己亲手写过,这个我就不清楚了,不管以前写没写,这一篇我们来玩一把. 一:概念 赫夫曼树里面有几个概念,也是非常简单的,先来看下面的图: 1. 基础概念 <1>  节点的权: 节点中红色部分就是权,在实际应用中,我们用“字符”出现的次数作为权. <2>  路径长度:可以理解成该节点到根节点的层数,比如:“A”到根节点

赫夫曼树编码的表示与实现--自己写数据结构

头文件huffman.h #ifndef _HUFFMAN_H_ #define _HUFFMAN_H_ #define MAX_WEIGHT 10000 typedef struct _HTNode { int weight; int parent,lchild,rchild; char data; }HTNode,*pHTNode; typedef char** huffmancode; void select_min_weight(HTNode* btree,int mn,int* s1,

贪心算法应用-哈夫曼编码

哈夫曼编码应用于数据文件和图像压缩的编码方式.其压缩率通常在20%~90%之间.在进行远距离通信时,通常需要把将要传送的文字转换为由二进制字符组成的字符串,并使要传送的电文总长度尽可能的短.显然只要将点文章出现次数多的字符采用尽可能短的编码,就可以减少要传送的电文总长度. 哈夫曼编码的核心思想: (1)每一个字符用一个0,1串作为其代码,并要求任意一个字符的代码都不是其他字符代码的前缀. (2)用字符在文件中出现的频率来建立一个用0,1串表示各字符的最优表示方式,即使出现频率高的字符获得较短编码

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

杂谈:最近有点慵懒,不好不好.好几天都没写代码,原本准备上星期完结 树 这一章节的.现在 又耽误了.哎.要抓紧时间啊. 下面直接上代码: 可以到我的网盘下载源代码,或者 直接拷贝下面的源代码 运行 网盘地址:点击打开链接 // HuffmanTree.cpp : 定义控制台应用程序的入口点. //哈弗曼编码,译码 #include "stdafx.h" #include <stdlib.h> #include <cstring> enum E_State { E