java实现-数据结构之二叉树(五):哈夫曼树的初识和代码构建

数据结构之二叉树(五):哈夫曼树

基本介绍:
给定n个权值作为n个叶子节点,若该树的带权路径长度(WPL)达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树
哈夫曼树是带权路径长度最短的树,权值最大的节点离根较近。

基本术语:
路径和路径长度
在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径。通路中分支的数目称为路径长度。若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1。

结点的权及带权路径长度
若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积。

树的带权路径长度
树的带权路径长度规定为所有叶子结点的带权路径长度之和,记为WPL。

举例说明:
在这里插入图片描述
该树的带权路径长度(WPL)=13x2+7x2+8x2+3x2=62

在这里插入图片描述
该树的带权路径长度为7x1+3x2+8x3+13x3=76

构建一棵哈夫曼树的步骤

1)从小到大进行排序,每一个数据都是一个节点,都可以看成一颗最简易的二叉树。
2)取出根节点权值最小的两棵二叉树组成一棵新的二叉树,该新的二叉树的根节点的权值是前面两棵二叉树根节点权值的和
3)再将这棵新的二叉树,以根节点的权值大小再次进行排序,不断重复这三步,直到所有数据全部被处理,便构建成了一棵哈夫曼树。

以下为举例说明:
权值为13,7,8,3,29,6,1的节点构建一棵二叉树。
首先对其进行升序排序:1,3,6,7,8,13,29

第一步:首先取出根节点权值最小的两棵树构建成一棵新的二叉树,即取1,3出来。变成如下:
在这里插入图片描述
**第二步:**新得的树的根节点的权值便成了4,接着让其加入剩下的节点再次排序,便是4,6,7,8,13,29,再次进行第一步(取4,6)得到图下:
在这里插入图片描述
第三步:将新得到的根节点权值为10的新树与剩下的树再次进行排序,得到7,8,10,13,29,再次进行第一步,得到图下:
在这里插入图片描述
**第四步:**得到的根节点权值为15的新树再次排序,得10,13,15,29,再次进行第一步得图下:
在这里插入图片描述
第五步:如此循环往复,直到所有节点皆被使用完,最终得到如下图:
在这里插入图片描述

**

java代码创建哈夫曼树

**:

package Tree05;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class HuffmanTree {
    
    
	public static void main(String[] args) {
    
    
		int arr[]= {
    
    13,7,8,3,29,6,1};
		Node root = createHuffmanTree(arr);
		frontShow(root);
	}
	//创建哈夫曼树
	public static Node createHuffmanTree(int[] arr) {
    
    
		//遍历arr数组,将arr的每个元素构建成一棵树(Node)
		//再将Node放入到ArrayList中
		List<Node> nodes=new ArrayList<Node>();
		for(int value: arr) {
    
    
			nodes.add(new Node(value));
		}
		while(nodes.size()>1) {
    
    
			//排序,升序
			Collections.sort(nodes);//node实现了Comparable接口,可以直接进行排序
			//取出权值最小的两棵二叉树
			Node leftNode=nodes.get(0);
			Node rightNode=nodes.get(1);
			//构建一棵新的二叉树
			Node parent=new Node(leftNode.value+rightNode.value);
			parent.left=leftNode;
			parent.right=rightNode;
			//从ArrayList中删除处理过的二叉树
			nodes.remove(leftNode);
			nodes.remove(rightNode);
			//将parent加入到nodes
			nodes.add(parent);
		}
		//返回哈夫曼树的root节点
		return nodes.get(0);
	}
	//前序遍历
	public static void frontShow(Node root) {
    
    
		if(root!=null) {
    
    
			root.frontShow();
		}else {
    
    
			System.out.println("空树,不能遍历");
		}
	}
}

//创建节点类
//便于节点按权值进行排序,实现Comparable接口
class Node implements Comparable<Node>{
    
    
	int value;//节点权值
	Node left;//左子节点
	Node right;//右子节点
	
	public Node(int value) {
    
    
		this.value=value;
	}

	@Override
	public String toString() {
    
    
		return "Node [value=" + value + "]";
	}
	
	@Override
	public int compareTo(Node o) {
    
    
		// TODO Auto-generated method stub
		//表示从小到大进行排序
		return this.value - o.value;
	}
	
	
	public void frontShow() {
    
    
		System.out.println(this);
		if(this.left!=null) {
    
    
			this.left.frontShow();
		}
		if(this.right!=null) {
    
    
			this.right.frontShow();
		}
	}
	
	
}

输出结果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_45273552/article/details/109122141
今日推荐