`
沉沦的夏天
  • 浏览: 10257 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

哈夫曼编码小结

阅读更多
哈夫曼树
哈夫曼树是一最优二叉树,假设有n个字节点Tn{T1,T2,……,Tn}的权值分别为
Wn{W1,W2,……,Wn},其构造方法
step1:想找出里面权值最小的两个节点,作为新建父节点的左右子树,父节点的权值step2:为这两个子节点的权值之和在Tn中将父节点的左右子树删除,并将父节点加进step3:重复1、2步,直到Tn只剩一个节点为止。
哈夫曼编码:当建好树后,从根开始,每层左子树标记为0,右子树标记为1,按此规律索引到叶节点,此顺序的01串即为该叶节点对应的哈夫曼编码。
下面是我的建树和打印哈夫曼编码过程(实现了简单的解码):


public class HalfmanTree {
	//key字符为value为字符的哈夫曼编码的map队列
	HashMap<String, String> map_pre= new HashMap<String, String>();
	//key字符为哈夫曼编码为字符的value的map队列,解码用的
	HashMap<String, String> map_dis= new HashMap<String, String>();
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		//String str="abbcccddddeeeee";
		//手动输入字符串
		Scanner sc=new Scanner(System.in);
		String str=sc.nextLine();
		//创建一个哈夫曼类
		HalfmanTree half=new HalfmanTree();
		//把字符串按不同字符统计权值,并存储到结点类数组中
		TreeNode [] arraynode=half.countstr(str);
		//根据结点类数组建立树
		TreeNode n=half.settree(arraynode);
		//打印叶节点中字符的哈夫曼编码,并已将编码放入map中
		half.print_hfm(n, "");
		
		//打印字符串的哈夫曼编码
		half.print_01(str);
		//打印解码的map
		half.print_map_dis();
		//打印解码后的字符串
		//System.out.println(half.discover_code("000 001	001	01	01	01	10	10	10	10	11	11	11	11	11"));
		
				
	} //主函数结束
	
	//以树节点中的权值大小为标准的比较器
	Comparator<TreeNode> com=new Comparator<TreeNode>() {
		@Override
		public int compare(TreeNode o1, TreeNode o2) {
			// TODO Auto-generated method stub
			if(o1.date>o2.date){
				return 1;
			}
			else
				return -1;
		}
	};
	
	//对字符串进行遍历,以各不同字符及对应权值创建结点类,保存到数组中返回
	public TreeNode [] countstr(String str){
		boolean flag_ever;//字符串重复标志
		//把第一个字符存入结点类队列的第一个
		ArrayList<TreeNode> listnode=new ArrayList<TreeNode>();	
		
		TreeNode node =new TreeNode();
		node.c=str.charAt(0);
		node.date=1;
	 	listnode.add(node);

		//从第二个开始遍历字符串
		for(int i=1;i<str.length();i++){
			flag_ever=false;
			//得到第i个字符
			char c=str.charAt(i);
			//遍历结点类队列
			for(int j=0;j<listnode.size();j++){
				//如果这个字符存在某个结点类中
				if(c==listnode.get(j).c){
					//把该几点权值计数加1
					listnode.get(j).date++;
					flag_ever=true;
					//结束循环
					break;
				}
			}
			//如果重复标志还是false,则表示没有重复的
			if(flag_ever==false){
				//那么应该新建一个节点,加入队列中
				TreeNode newnode =new TreeNode();
				newnode.c=c;
				newnode.date=1;
			 	listnode.add(newnode);
			 	//System.out.println(listnode.size());
			}
		}
		
		//将节点类队列的节点存到数组中
		TreeNode [] arraynode=new TreeNode[listnode.size()];
		for(int i=0;i<arraynode.length;i++){
			arraynode[i]=listnode.get(i);
//			System.out.println(listnode.get(i).c);
//			System.out.println(listnode.get(i).date);
		}
		
		return arraynode;
	}
	
	
	//由结点类数组创建一个树,返回根节点
	public TreeNode settree(TreeNode node_array[]){
		//直到只有一个节点时结束
		while(node_array.length>1){
			//对数组进行排序,按照com比较器
			Arrays.sort(node_array, com);
			//由最小两个数的所在节点创建父节点
			TreeNode node=new TreeNode();
			node.left=node_array[0];
			node.right=node_array[1];
			node.date=node_array[0].date+node_array[1].date;
			//创建新节点数组,长度减一
			TreeNode[] newnode_array=new TreeNode[node_array.length-1];
			for(int i=2;i<node_array.length;i++){
				newnode_array[i-2]=node_array[i];
			}
			newnode_array[node_array.length-2]=node;
			//把新节点数组首地址赋给院节点数组
			node_array = newnode_array;
		}
		//最后一个节点即根节点,赋哈夫曼编码,并返回根节点
		node_array[0].s="";
		return node_array[0];
	}
	
	//打印二叉树编码
	public void print_hfm(TreeNode node,String  code){
		//有节点存在时
		if(node!=null){
			
//			if(node.left ==null && node.right==null){
//			System.out.println(node.c+"的哈夫曼编码为:"+code);
//	
//			}
//			print_hfm(node.left, code+"0");
//			print_hfm(node.right, code+"1");
			//该节点为叶子节点时
			if(node.left ==null && node.right==null){
				System.out.println(node.c+"的哈夫曼编码为:"+node.s+" 权数为:"+node.date);
				map_pre.put(""+node.c, node.s);
				map_dis.put(node.s,""+node.c);
				
			}
			//左子树为空时,打印哈夫曼编码
			if(node.left!=null){
				node.left.s=node.s+"0";
				print_hfm(node.left,node.left.s);
			}
			//右子树为空时,打印哈夫曼编码
			if(node.right!=null){
				node.right.s= node.s+"1";
				print_hfm(node.right,node.right.s);
			}
			
		}
		
	}
	//按字符输出哈夫曼编码
	public void print_01(String str){
		System.out .println(str+"各字符对应编码为:");
		for(int i=0;i<str.length();i++){
			char ch= str.charAt(i);
			String code=map_pre.get(""+ch);
			System.out.print(code+'\t');//每个编码直接加tab键间隔
		}
		System.out .println();
	}
//测试打印map_dis
	public void print_map_dis (){
		Set<Entry<String, String>> entry=map_dis.entrySet();
		for(Entry<String, String> en : entry ){
			System.out.println("键"+en.getKey()+"的值为:"+en.getValue());
		}
	}
	//解码
	public String discover_code(String str_str){
		//String str="000001";
		String discode="";
		Set<String> set=map_dis.keySet();
		String s="";
		for(int i=0;i<str_str.length();i++){
			if(str_str.charAt(i)!='\t'&&str_str.charAt(i)!=' '){
				System.out.println(i);
				s=s+str_str.charAt(i);
				for(String ss :set){
					if(s.equals(ss)){
						discode=discode+map_dis.get(s);
						s="";
						break;
					}
				}
			}
			
		}
		return discode;
	}
	
}




这只是个简单的给哈夫曼树编码,应用的话可以做个解约软件,有待突破!!!!
2
2
分享到:
评论

相关推荐

    数据结构5哈夫曼树和哈夫曼编码.ppt

    哈夫曼树和哈夫曼编码是数据结构中的一种重要概念,哈夫曼树是一种特殊的二叉树,它可以用来构造最优的前缀编码。哈夫曼编码是一种变长编码方法,它可以使得总的编码长度最短。 哈夫曼树的定义是指带权路径长度最小...

    C语言编码哈夫曼树

    //动态分配数组存储哈夫曼编码表 //-------全局变量-------- HuffmanTree HT; HuffmanCode HC; int *w;//权值数组 //const int n=26;//字符集的个数 char *info;//字符值数组 int flag=0;//初始化标记 //*****...

    哈夫曼编码动态绘制小软件,是大二做的一份结课作业

    小程序提供了两种功能的哈夫曼编码方式: 一、读取本地文件的字符: 对其进行哈夫曼编码后输出编码后的文件到指定文本文件。 二、用户输入待分析字符: 编码结果在用户界面直接显现,并同时提供了解码、...

    构造哈夫曼树之后,求每一个字符的编码需要走一条从叶子结点到根结点的路径

    在哈夫曼树中,没有度为1的结点,结点总数是n0+n2(其中n0表示二叉树中度为0的结点数,n2表示度为2的结点数),而由二叉树的性质知道n0=n2+1,所以一棵哈夫曼树中结点总数是2n0-1。 由此可以得出:任何n个字符的...

    课程设计哈夫曼树的应用

    2.1哈夫曼编码/译码器简介 4 2.2. 问题描述 4 2.3需求分析 4 3.概要设计 5 3.1问题分析哈夫曼树的定义 5 4.详细设计 6 4.1 系统框架图 6 4.2 总体流程图 7 4.3编码函数 8 4.4译码函数 10 4.5运行结果 11 5.调试分析 ...

    哈夫曼树 c数据结构

    利用哈夫曼编码进行信息通讯可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码;在接收端将传来的数据进行译码(复原)。对于双工信道(即可以...

    哈夫曼压缩

    利用哈夫曼编码进行信息通讯可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码;在接收端将传来的数据进行译码(复原)。对于双工信道 (即可以双向...

    哈弗曼编码 - 数据结构课程 设计报告

    摘要 2 目录 3 一.设计目的 3 二....2.1哈夫曼编码/译码器简介 5 2.2需求分析 5 三.概要设计 5 3.1问题分析哈夫曼树的定义 5 四.详细设计 7 4.1 源代码 7 4.2运行结果 22 五.调试分析 23 六.小结 25

    第六章 树和二叉树作业及答案(100分).docx

    1. 一棵二叉树的顺序存储情况如下: 树中,度为2的结点数为( )。 A.1 B.2 C.3 D.4 2. 一棵“完全二叉树”结点数为25,高度为( )。 A.4 B.5 C.6 D....3.下列说法中,( )是...(2)哈夫曼编码方案(4分):

    C#数字图像处理算法典型实例.iso

    C#数字图像处理算法典型实例随书光盘 精选数字图像处理领域中的一些应用实例,以理论和实践相结合的方式,系统地介绍了如何使用C#进行数字图像处理。 C#数字图像处理算法典型实例共11章,分别讲述了... 11.8 小结

    赫夫曼编码(C语言版本)

    typedef struct { /*哈夫曼编码结信息的构*/ char bit[MAXBIT]; int start; }Hcodetype; typedef struct { /*哈夫曼树结点的结构*/ int weight; int parent; int lchild; int rchild; char ch; }...

    算法设计与分析王晓东

    小结 习题 第2章 递归与分治策略 2.1 速归的概念 2.2 分治法的基本思想 2.3 二分搜索技术 2.4 大整数的乘法 2.5 Strassen矩阵乘法 2.6 棋盘覆盖 2.7 合并排序 2.8 快速排序 2.9 线性时间选择 2.10 最接近点对问题 ...

    java数据结构与算法第二版

    目录 出版说明 献词 简介 第1章 综述 ... 哈夫曼(Huffman)编码 小结 问题 实验 编程作业 第9章 红-黑树 第10章 2-3-4树和外部存储 第11章 哈希表 第12章 堆 第13章 图 第14章 带权图 第15章 应用场合

    Java数据结构和算法(第二版)

    哈夫曼(Huffman)编码 小结 问题 实验 编程作业 第9章 红-黑树 第10章 2-3-4树和外部存储 第11章 哈希表 第12章 堆 第13章 图 第14章 带权图 第15章 应用场合 附录A 运行专题applet和示例程序 附录B 进一步学习 附录...

    算法设计与分析:动态规划、贪心与分治策略在优化问题中的应用与实践

    实验任务多样,涉及矩阵链相乘问题、投资问题、背包问题、旅行商问题(TSP)、数字三角形、哈夫曼编码、顾客等待时间最短问题、最小生成树问题、图着色问题、八皇后问题、连续邮资问题、卫兵布置问题、圆排列问题、...

    Java数据结构和算法中文第二版

    哈夫曼(Huffman)编码 小结 问题 实验 编程作业 第9章 红-黑树 第10章 2-3-4树和外部存储 第11章 哈希表 第12章 堆 第13章 图 第14章 带权图 第15章 应用场合 附录A 运行专题applet和示例程序 附录B 进一步学习 ...

    数据结构与算法分析_Java_语言描述

    参考文献 第10章 算法设计技巧 10.1 贪婪算法 10.1.1 一个简单的调度问题 10.1.2 哈夫曼编码 10.1.3 近似装箱问题 10.2 分治算法 10.2.1 分治算法的运行时间 10.2.2 最近点问题 10.2.3 选择问题 ...

    突破程序员基本功的16课.part2

    11.5.3 哈夫曼编码 11.6 排序二叉树 11.7 红黑树 11.7.1 插入操作 11.7.2 删除操作 11.8 小结 第12课 常用的内部排序 12.1 排序的基本概念 12.1.1 排序概述 12.1.2 内部排序的分类 12.2 选择排序法 ...

    数据结构与算法分析Java语言描述(第二版)

    算法设计技巧10.1 贪婪算法10.1.1 一个简单的调度问题10.1.2 哈夫曼编码10.1.3 近似装箱问题10.2 分治算法10.2.1 分治算法的运行时间10.2.2 最近点问题10.2.3 选择问题10.2.4 一些算术问题的理论改进10.3 动态规划...

Global site tag (gtag.js) - Google Analytics