哈夫曼树实现

#include <iostream>
#include <cstdio>
#define inf 1<<30
using namespace std;
//哈夫曼树实现
//哈夫曼树的特征:如果有n个叶子节点的话,则总结点数为2*n-1。越频繁访问的编码越短
struct node
{
	int parent, lson, rson;
	int val;      //访问次数
};

void createTree(node p[], int n, int total)   //total=2*n-1
{
	for(int t=0; t<total; ++t)  //初始化
	{
		p[t].parent = p[t].lson = p[t].rson = -1;
	}
	for(int i=n; i<total; ++i)
	{
		int min1, min2, l, r;   //最大值和第二大值
		min1 = min2 = inf;
		l = r = -1;
		for(int t=0; t<i; ++t)   //遍历寻找两个最小的点,也就是val值最小的
		{
			if(p[t].parent == -1)
			{
				if(p[t].val<min1)
				{
					r = l;
					l = t;
					min2 = min1;
					min1 = p[t].val;
				} else if(p[t].val<min2){
					r = t;
					min2 = p[t].val;
				}
			}
		}
		p[i].val = min1 + min2;
		p[l].parent = p[r].parent = i;
		p[i].lson = l;
		p[i].rson = r;
	}
}

struct code
{
	int k;
	char c[100];
};

void huffmancode(node p[], int n, code c1[])
{
	for(int t=0; t<n; ++t)
	{
		int pre = p[t].parent;
		int g = t;
		c1[t].k = 0;
		while(pre != -1)
		{
			if(p[pre].lson == g)
			{
				c1[t].c[c1[t].k++] = '0';
			} else {
				c1[t].c[c1[t].k++] = '1';
			}
			g = pre;
			pre = p[pre].parent;
		}
		c1[t].k--;
	}
}

int main()
{
	node p[4*2-1];
	for(int t=0; t<4; ++t)
	{
		p[t].val = 2*t+1;
	}
	createTree(p, 4, 2*4-1);
	code c[4];
	huffmancode(p, 4, c);

	for(int t=0; t<4; ++t)
	{
		int k = c[t].k;
		printf("%d:", p[t].val);
		for(int j=k; j>=0; --j)
		{
			printf("%c", c[t].c[j]);
		}
		printf("\n");
	}
	return 0;
}

运行结果:

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-15 13:37:32

哈夫曼树实现的相关文章

由二叉树构造赫夫曼树

赫夫曼树: 假设有n个权值{w1,w2,w3....},试构造一棵具有n个叶子节点的二叉树,每个叶子节点带权为wi,则其中带权路径长度最小的二叉树称为最优二叉树或者叫赫夫曼树. 构造赫夫曼树: 假设有n个权值,则构造出的赫夫曼树有n个叶子节点,n个权值分别设置为w1,w2,....wn,则赫夫曼树的构造规则为: 1.将w1,w2...看成是有n棵树的森林: 2.在森林中选择两个根节点的权值最小的树合并,作为一棵新树的左右子树,且新树的根节点权值为其左右子树根节点权值之和: 3.从森林中删除选取的

php 二叉树 与赫夫曼树

在学习图之前,中间休息了两天,感觉二叉树需要消化一下.所以中间去温习了下sql,推荐一本工具书<程序员的SQL金典>看名字不像一本好书,但是作为一个不错的SQL工具书还是可以小小备忘一下.涵盖内容不详细但是挺广,覆盖多种主流数据库 言归正传,以前知道折半查找,二叉树的概念也是感觉挺有意思,二叉树的实现有一个案例很不错,代码如下 class BiNode{ public $data; public $lchild; public $rchild; public function __constr

哈夫曼树与哈夫曼编码

哈夫曼树与哈夫曼编码 术语: i)路径和路径长度 在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径. 路径中分支的数目称为路径长度.若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1. ii)结点的权及带权路径长度 若对树中的每个结点赋给一个有着某种含义的数值,则这个数值称为该结点的权. 结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积. iii)树的带权路径长度 树的带权路径长度:所有叶子结点的带权路径长度之和,记为WPL. 先了解一下

数据结构之哈夫曼树

#include <iostream> #include <iomanip> #include <string> using namespace std; typedef struct { string name; int weight; int parent, lchild, rchild; int visited; //设置visited选项来表示每次查找最小权值后的删除,0代表未删除,1表示删除 }HTNode,*HuffmanTree; int Min(Huff

Huffman tree(赫夫曼树、霍夫曼树、哈夫曼树、最优二叉树)

flyfish 2015-8-1 Huffman tree因为翻译不同所以有其他的名字 赫夫曼树.霍夫曼树.哈夫曼树 定义引用自严蔚敏<数据结构> 路径 从树中一个结点到另一个结点之间的分支构成两个结点之间的路径. 路径长度 路径上的分支数目称作路径长度. 树的路径长度 树的路径长度就是从根节点到每一结点的路径长度之和. 结点的带权路径长度 结点的带权路径长度就是从该结点到根节点之间的路径长度与结点上权的乘积. 树的带权路径长度 树的带权路径长度就是树中所有叶子结点的带权路径长度之和,通常记做

数据结构之哈夫曼树(java实现)-(五)

所谓哈夫曼树就是要求最小加权路径长度,这是什么意思呢?简而言之,就是要所有的节点对应的路径长度(高度-1)乘以该节点的权值,然后保证这些结果之和最小. 哈夫曼树最常用的应用就是解决编码问题.一般我们用的ASCII是固定长度的编码,对于那些常用的字符,使用很长的长度就显得略为浪费空间了. 下面以一个实例来构建一颗哈夫曼编码树. 设字符集S={A,B,C,D,E,F},字符出现的频率W={2,3,5,7,9,12},对字符集进行哈夫曼编码 (1)以频率为树的节点值,构建6个树节点,保存在一个数据集合

《数据结构复习笔记》--哈夫曼树,哈夫曼编码

先来了解一下哈夫曼树. 带权路径长度(WPL):设二叉树有n个叶子结点,每个叶子结点带有权值 wk,从根结点到每个叶子结点的长度为 lk,则每个叶子结点的带权路径长度之和就是: 最优二叉树或哈夫曼树: WPL最小的二叉树. [例]有五个叶子结点,它们的权值为{1,2,3,4,5},用此权值序列可以构造出形状不同的多个二叉树. 其中结果wpl最小值的是:33=(1+2)*3+(3)*2+(4+5)*2: 哈夫曼树的构造: 每次把权值最小的两棵二叉树合并, 代码: typedef struct Tr

哈夫曼树学习笔记

既然我们要学习赫夫曼树,那么我们首先就要知道什么叫赫夫曼树. 那么什么叫赫夫曼树呢? 一.什么叫赫夫曼树? 书上说:“赫夫曼(Huffman)树又称最优树,是一类带权路径长度最短的树,但是我们仅学习最优二叉树.” 看到这个还是不明白什么意思,因此在学习之前我们要结合这个图了解几个基本概念. 路    径:由一结点到另一结点间的分支所构成.如:a->b a->b->e 路径长度:路径上的分支数目,如:a→e的路径长度=2  a->c的路径长度=1 树的路径长度:从树根到每一结点的路径

[转]哈夫曼树

  一.哈夫曼树的概念和定义 什么是哈夫曼树? 让我们先举一个例子. 判定树:         在很多问题的处理过程中,需要进行大量的条件判断,这些判断结构的设计直接影响着程序的执行效率.例如,编制一个程序,将百分制转换成五个等级输出.大家可能认为这个程序很简单,并且很快就可以用下列形式编写出来: if(score<60) cout<<"Bad"<<endl; else if(score<70) cout<<"Pass"

hdu5884 Sort(二分+k叉哈夫曼树)

题目链接:hdu5884 Sort 题意:n个有序序列的归并排序.每次可以选择不超过k个序列进行合并,合并代价为这些序列的长度和.总的合并代价不能超过T, 问k最小是多少. 题解:先二分k,然后在k给定的情况下,构造k叉哈夫曼树.O(nlogn)的做法:先对所有数排序,另外一个队列维护合并后的值,取值时从两个序列前端取小的即可. 注:如果(n-1)%(k-1)!=0,那么就要增加(k-1-(n-1)%(k-1))个权值为0的叶子节点作虚拟点. 1 #include<cstdio> 2 #inc