`
zhouYunan2010
  • 浏览: 206280 次
  • 性别: Icon_minigender_1
  • 来自: 湖南
社区版块
存档分类

最优二叉树(哈弗曼树)

阅读更多
   提到哈弗曼树就必须提到节点权值,权值一般具有实际意义,比如此节点出现的概率,次数等。
必须提供权值才能构建出一棵哈弗曼树,因为哈弗曼树的定义为带权路径长度最小的二叉树。
树的带权路径长度为所有叶子节点的带权路径长度。
节点的带权路径长度为该节点到树的路径长度乘以节点权值。
哈希曼树最主要的应用是产生哈希曼编码。
为特点元素设计哈希曼编码要求二进制编码尽可能的短,并且任意一个字符的编码不是另外一个
字符的编码的前缀。


下面通过java代码构建哈希曼树与设计哈希曼编码
package com.algorithm;

/**
 * 最优二叉树(哈夫曼树)
 * 根据元素的权值构建哈夫曼树,并设计其哈弗曼编码
 * 使用数组存储节点
 */
public class Hufuman {
	private int[] weights;		//存储权值
	private int n;
	private TreeNode[] nodes;	//存储节点的数组
	private int m;		//数组长度
	
	
	class TreeNode{
		int weight;		//权值
		int Parent;		//父节点的下标
		int lchild;		//左孩子下标
		int rchild;		//右孩子下标
		
		public TreeNode(int weight,int parent,int lchild,int rchild){
			this.weight = weight;
			this.Parent = parent;
			this.lchild = lchild;
			this.rchild = rchild;
		}
	}
	
	public Hufuman(){
		
	}
	
	public Hufuman(int[] w){
		this.weights = w;
		int n = w.length;
		if(n <= 1){
			throw new IllegalArgumentException();
		}
		this.n = n;
		init();
	}
	
	/**
	 * 初始化节点数组
	 */
	private void init(){
	    m = 2*n - 1;
		nodes = new TreeNode[m];
		int i;
		for(i = 0;i < n ;++i){
			nodes[i] = new TreeNode(weights[i], -1, -1, -1);	//-1表示无父或孩子节点
		}
		for(;i < m;++i){
			nodes[i] = new TreeNode(-1, -1, -1, -1);
		}
	}
	
	/**
	 * 根据权值构建哈夫曼树
	 */
	public void create(){
		int min,secmin;
		for(int i = n;i < m;++i){
			int[] mins = select(i-1);
			min = mins[0];
			secmin = mins[1];
			nodes[min].Parent = i ;
			nodes[secmin].Parent = i;
			nodes[i].lchild = min;
			nodes[i].rchild = secmin;
			nodes[i].weight = nodes[min].weight + nodes[secmin].weight;

		}
	}
	
	/**
	 * 从叶子节点逆向求每个字符的哈弗曼编码
	 */
	public String[] hufumanCoding(){
		String[] codes = new String[n];
		StringBuilder sb ;
		for(int i=0;i<n;++i){	//i到n都是叶子节点
			sb = new StringBuilder();
			for(int c=i,p=nodes[i].Parent;p!=-1;c=p,p=nodes[p].Parent){
				if(nodes[p].lchild == c)
					sb.append('0');		//左分支表示字符'0'
				else	
					sb.append('1');		//右分支表示字符'1'
			}
			codes[i] = sb.reverse().toString();
		}
		return codes;
	}
	
	/**
	 * 取weight最小的两个节点
	 */
	private int[] select(int last){
		int min=0;		//最小值下标
		int secmin=0;		//次小值下标
		int i;
		for(i=0;i<=last;++i){
			if(nodes[i].Parent==-1){
				min = i;
				break;
			}
		}
		for(i=i+1;i<=last;++i){
			if(nodes[i].Parent==-1){
				secmin = i;
				break;
			}
		}
		int temp;
		if(nodes[min].weight > nodes[secmin].weight){
			temp = min;
			min = secmin;
			secmin = temp;
		}
		for(i=i+1;i<=last;++i){
			if(nodes[i].Parent!=-1)continue;
			if(nodes[i].weight < nodes[min].weight){
				secmin = min;
				min = i;
			}else{
				if(nodes[i].weight < nodes[secmin].weight)
					secmin = i;
			}
		}
		int[] minValues = {min,secmin};
		return minValues;
	}
	
	public void printTree(){
		System.out.println("   | weight | parent | lchild | rchild |");
		for(int i=0;i<m;i++){
			System.out.print(i+"  |   "+nodes[i].weight+"   |   "+nodes[i].Parent+"   |   "+nodes[i].lchild+"   |   "+nodes[i].rchild+"   |");
			System.out.println();
		}
	}
	
	public static void main(String[] args) {
		int[] w = {5,29,7,8,14,23,3,11};
		Hufuman t = new Hufuman(w);
		t.create();
		t.printTree();
		String[] str = t.hufumanCoding();
		for(String s:str){
			System.out.println(s);
		}
	}
		
}


分享到:
评论

相关推荐

    C++哈弗曼树

    哈弗曼树 给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树 C++实现哈弗曼树

    数据结构课程设计 包括 链表 共享栈 队列 二叉树与哈弗曼树

    实验一_线性表(顺序表) 实验二_线性链表 实验三_共享栈操作 实验四_队列操作 实验五_二叉树与最优二叉树

    C++哈弗曼树、编码

    对哈弗曼树进行构建最优二叉树,斌对其进行编码,

    哈弗曼编码信息论设计数据结构设计

    本程序是最优二叉树,哈弗曼编码,可用于信息论课程设计以及数据结构课程设计。

    哈夫曼树的介绍.pdf

    当用 n 个结点(都做叶子结点且都有各自的权值)试图构建一棵树时,如果构建的这棵树的带权路径长度最小,称这棵树为“最优二叉树”,有时也叫“赫夫曼树”或者“哈夫曼树”。 在构建哈弗曼树时,要使树的带权路径...

    哈夫曼树&哈弗曼编码

    哈夫曼树 给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman tree)。用c++实现构造哈夫曼树、哈夫曼编码。

    数据结构实验报告 哈弗曼编码建立 建立二叉树 纸牌游戏 文章编辑

    程序源代码 函数调用 程序说明 .一元多项式计算: 任务:能够按照指数降序排列建立并输出多项式;... 任务:建立最优二叉树函数。 要求:可以建立函数输入二叉树,并输出其哈夫曼树。 (程序输出的是哈夫曼编码)

    c语言哈夫曼数

    当用 n 个结点(都做叶子结点且都有各自的权值)试图构建一棵树时,如果构建的这棵树的带权路径长度最小,称这棵树为“最优二叉树”,有时也叫“赫夫曼树”或者“哈夫曼树”。 在构建哈弗曼树时,要使树的带权路径...

    C语言构造哈夫曼树.rar

    给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。

    基于C++ 哈夫曼编码 实现(控制台)文件加密系统【100010605】

    在技术上对哈弗曼编码中的最优二叉树进行改进,由二叉树变为三叉树(森林),减少了编码文件的空间,并且在编码过程中我们采用动态分配叶子的方法,一旦密码本中的字符计数出现增加或者减少,或者说密码本中字符的...

    数据结构课程设计 哈弗曼压缩+纸牌游戏

    哈夫曼编码就是利用这一点,以字符作为叶子结点,以其频率作为权值,建立最优二叉树。 一 下面先重点讨论一下建立哈夫曼数的算法。哈夫曼算法: 根据给定叶子结点及其权值(这里即字符及其频率)构成二叉树的集合,...

Global site tag (gtag.js) - Google Analytics