`
19941021
  • 浏览: 5365 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
最近访客 更多访客>>
社区版块
存档分类
最新评论
  • ayaome: ...
    java
  • 19941021:     明白了!谢谢了!
    java
  • ayaome: head属于LinkList类的属性你加个static关键字, ...
    java
  • 19941021:      这是因为在主函数中调用遍历链表的方法时要传入链表头的 ...
    java
  • ayaome: public static LinkNode head=nul ...
    java
阅读更多
  哈夫曼树又称最优二叉树,即WPL(树中所有叶子结点的带权路径长度之和)。
   
    给定n个权值集合W构造n棵二叉树的集合F:
   构建方式如下:
   (1)把所有权值按从小到大的顺序排列,权值最小的作为根结点,其左右子数为空
   (2)在F中找出两颗根结点权值最小的数作为左右子数构造新的二叉树, 新的二叉树权值为左右子树结点权值之和
   (3)将新的二叉树加入到F中,再和剩余权值最小结点作为子树创建新的二叉树
   (4)重复(3)直到F中只有一棵树
   
    哈弗曼树编码:
       从根结点开始,对左子树分配0,右子树分配1,一直到达叶子结点为止
       然后从树根沿每条路径到达叶子节点的代码排列起来,就得到哈弗曼编码了

    在下表达能力差也许没说明白,下面有个具体例子,阁下可以参考一下:
    例如一个文件中有字母A5个,B6个,C10个,D4个,E2个
    构建的二叉树如下图
      
    接下来就是代码的实现了。
     首先明确自己的目的:
     从键盘任意输入一个字符串,用一个方法来统计每个字符的权值
     然后根据权值创建二叉树然后编码

     这个过程我遇到这样一个问题:
     最好用Map集合存储每个字符和其权值,这样既保证每个字符和权值的对应关系,而且Map集合中的字符可以是字母,汉字,数字,和其他的字符;
    如果用数组,要分几种情况讨论,难点在于汉字和其他字符的遍历          

 
 //哈弗曼树节点类                                    
 public class HfmNode {
   public HfmNode left;  //左子叶
   public HfmNode right;  //右子叶
   public int data;   //字符的频率
    public char c;    //字符的种类  
   
}


 
//创建二叉树的类
import java.util.Arrays;
import java.util.Date;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeMap;
public class HFMstr {
	private HfmNode[] nodes;  //结点数组
	private static char[] charArray;  //字符数组
	private static String st="";   //定义从键盘输入的字符串
	private static TreeMap<Character,Integer> tm; //存储字符和其对应的频率
	
	/**
	 * 传入字符串,先转化为字符数组
	 * 再用TreeMap存储每个字符和其对应的频率
	 * 最后转化为结点数组
	 * @param str
	 */
	public HFMstr(String str){
		charArray=str.toCharArray();
		tm = new TreeMap<Character,Integer>();
		for (int x = 0; x < charArray.length;x++ ){  //遍历字符数组
			  if(!tm.containsKey(charArray[x])){              
                tm.put(charArray[x],1);   //向TreeMap中加入字符和他对应的频率
            }else{
          	  int count =tm.get(charArray[x])+1;  //count为当前字符的频率
          	  tm.put(charArray[x],count); 
            }
			 
		 }		 
		
		nodes = new HfmNode[tm.size()];  //按照char数组的长度创建创建结点数组
		Set<Character> set = tm.keySet(); //从set集合中取出char字符
		int n=0;
		for(Character c : set){
			nodes[n] = new HfmNode(); 
			nodes[n].c=c;
			nodes[n].data=tm.get(c);   //得到相应字符的频率
			n++;
		}
	}
		
	//对节点数组排序
	private void sort(HfmNode[] nodes){
		//冒泡排序
		for(int i=0; i<nodes.length; i++){
			for(int j=i+1; j<nodes.length; j++){
				if(nodes[i].data > nodes[j].data){
					//交换:注意,交换的是位置,而不是属性									
					HfmNode n = nodes[i];
					nodes[i] = nodes[j];
					nodes[j] = n;
				}
			}
		}
	}
	
	//创建哈弗曼树
	private HfmNode createTree(){
		HfmNode[] nodes = this.nodes;
		while(nodes.length > 1){			
			sort(nodes);
			//取前面两个最小的节点
			HfmNode n1 = nodes[0];
			HfmNode n2 = nodes[1];
			//创建新节点
			HfmNode n3 = new HfmNode();
			n3.left = n1;
			n3.right = n2;
			n3.data = n1.data+n2.data;
			
			//新建一个长度比原来小1的数组
			HfmNode[] nodes2 = new HfmNode[nodes.length-1];
			for(int i=2; i<nodes.length;i++){
				nodes2[i-2] = nodes[i];
			}
			//把新节点加进来
			nodes2[nodes2.length-1] = n3;				
			nodes = nodes2;
		}		
		return nodes[0];
	}
	
	//打印节点
	public void printCode(){
		HfmNode root = createTree();  //得到二叉树的根结点
		printHFM(root,"");
	}
	
	//打印编码
	public void printHFM(HfmNode node, String code){
	
		if(node != null){
			if(node.left == null && node.right == null){	//输出的是叶子				
				System.out.println(node.c+"的编码是"+code+" "+" " +"权数是"+node.data);
			}
			//利用递归打印编码
			printHFM(node.left,code+"0");
			printHFM(node.right,code+"1");
		}
	}
	
	//入口函数
	 public static void main(String args[]){	        
	     Scanner sc = new Scanner(System.in); 
	     st = sc.nextLine(); //从键盘中输入一个字符串
	     
	     HFMstr  hs=new   HFMstr(st);
	     hs.printCode();
	 }
	            

}

//程序测试
运行结果如下:

   这就是哈弗曼树的基本操作了。




  • 大小: 7 KB
  • 大小: 56.3 KB
分享到:
评论

相关推荐

    JAVA_API1.6文档(中文)

    java.lang.management 提供管理接口,用于监视和管理 Java 虚拟机以及 Java 虚拟机在其上运行的操作系统。 java.lang.ref 提供了引用对象类,支持在某种程度上与垃圾回收器之间的交互。 java.lang.reflect 提供类...

    Java 面经手册·小傅哥.pdf

    这是一本以面试题为入口讲解 Java 核心内容的技术书籍,书中内容极力的向你证实代码是对数学逻辑的具体实现。当你仔细阅读书籍时,会发现Java中有大量的数学知识,包括:扰动函数、负载因子、拉链寻址、开放寻址、...

    java源码包---java 源码 大量 实例

    Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这款实例会对你有所帮助。 Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来模拟银行ATM...

    JAVA上百实例源码以及开源项目

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    java源码包2

    Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这款实例会对你有所帮助。 Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来模拟银行...

    java源码包4

    Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这款实例会对你有所帮助。 Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来模拟银行...

    java源码包3

    Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这款实例会对你有所帮助。 Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来模拟银行...

    java api最新7.0

    JAVA开发人员最新版本7.0 api文档!本文档是 Java Platform Standard Edition 7 的 API !Java 1.7 API的中文帮助文档。 深圳电信培训中心 徐海蛟博士教学用api 7.0中文文档。支持全文检索,在线即时查询。 里面列...

    java开源包11

    JoSQL(SQLforJavaObjects)为Java开发者提供运用SQL语句来操作Java对象集的能力.利用JoSQL可以像操作数据库中的数据一样对任何Java对象集进行查询,排序,分组。 搜索自动提示 Autotips AutoTips是为解决应用系统对于...

    java开源包4

    JoSQL(SQLforJavaObjects)为Java开发者提供运用SQL语句来操作Java对象集的能力.利用JoSQL可以像操作数据库中的数据一样对任何Java对象集进行查询,排序,分组。 搜索自动提示 Autotips AutoTips是为解决应用系统对于...

    java开源包6

    JoSQL(SQLforJavaObjects)为Java开发者提供运用SQL语句来操作Java对象集的能力.利用JoSQL可以像操作数据库中的数据一样对任何Java对象集进行查询,排序,分组。 搜索自动提示 Autotips AutoTips是为解决应用系统对于...

    java开源包9

    JoSQL(SQLforJavaObjects)为Java开发者提供运用SQL语句来操作Java对象集的能力.利用JoSQL可以像操作数据库中的数据一样对任何Java对象集进行查询,排序,分组。 搜索自动提示 Autotips AutoTips是为解决应用系统对于...

    java开源包5

    JoSQL(SQLforJavaObjects)为Java开发者提供运用SQL语句来操作Java对象集的能力.利用JoSQL可以像操作数据库中的数据一样对任何Java对象集进行查询,排序,分组。 搜索自动提示 Autotips AutoTips是为解决应用系统对于...

    java开源包8

    JoSQL(SQLforJavaObjects)为Java开发者提供运用SQL语句来操作Java对象集的能力.利用JoSQL可以像操作数据库中的数据一样对任何Java对象集进行查询,排序,分组。 搜索自动提示 Autotips AutoTips是为解决应用系统对于...

    java开源包10

    JoSQL(SQLforJavaObjects)为Java开发者提供运用SQL语句来操作Java对象集的能力.利用JoSQL可以像操作数据库中的数据一样对任何Java对象集进行查询,排序,分组。 搜索自动提示 Autotips AutoTips是为解决应用系统对于...

    Java开发技术大全(500个源代码).

    HelloWorldApp.java 第一个用Java开发的应用程序。 firstApplet.java 第一个用Java开发的Applet小程序。 firstApplet.htm 用来装载Applet的网页文件 第2章 示例描述:本章介绍开发Java的基础语法知识。 ...

    java开源包1

    JoSQL(SQLforJavaObjects)为Java开发者提供运用SQL语句来操作Java对象集的能力.利用JoSQL可以像操作数据库中的数据一样对任何Java对象集进行查询,排序,分组。 搜索自动提示 Autotips AutoTips是为解决应用系统对于...

    java开源包3

    JoSQL(SQLforJavaObjects)为Java开发者提供运用SQL语句来操作Java对象集的能力.利用JoSQL可以像操作数据库中的数据一样对任何Java对象集进行查询,排序,分组。 搜索自动提示 Autotips AutoTips是为解决应用系统对于...

    Java 中文入门学习手册合集[chm版]

    第一章 Java语言的产生及其特点 第二章 Java程序开发与运行环境 第三章 Java程序设计基础 第四章 Java应用程序的基本框架 第五章 Java的类 第六章 Java图形用户接口 第七章 多线程 第八章 Java的"异常" 第九...

Global site tag (gtag.js) - Google Analytics