Java---Huffman树的实现

Posted 坦荡的火星

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java---Huffman树的实现相关的知识,希望对你有一定的参考价值。

什么是哈弗曼树

1.哈弗曼树是最优二叉树,树的带权路径长度最小的一个二叉树。

2.带权路径长度为根节点到该节点的路径长度和该节点权重的乘积。
3.路径长度为当前节点到另一个节点所经过的分支的个数(边的个数)。

应用场景

哈弗曼树可以用来求哈弗曼编码,通过对文件中不同数据出现的频率,
设计出新的编码方式,来对文件进行数据压缩。

建立哈弗曼树

.将表示不同数据的节点按照出现的频率(权重)进行排序。

2.选取出两个最小频率(权重)的数据,创建新节点,作为新节点的两个子节点。
3.将两个子节点从原有的节点集删除,计算新节点的权重,并将其加入到节点集合中。
4.对新的节点集进行排序,重复2和3步骤,直到节点集中只有一个节点。

代码实现

package com.newer.tree;

/**
 * 哈弗曼树中每个节点的信息
 * 
 * @author lixiaochi
 *
 */
public class HuffmaNode {
    // 当前节点的数据
    String name;
    // 当前节点的权重
    int value;
    // 当前节点所对应的哈弗曼编码
    String encode;

    // 当前节点的左右子节点
    HuffmaNode leftChild;
    HuffmaNode rightChild;

    // Hafuman节点的构造方法
    public HuffmaNode(String name, int value) {
        super();
        this.name = name;
        this.value = value;
    }

    public HuffmaNode(String name, int value, HuffmaNode leftChild, HuffmaNode rightChild) {
        super();
        this.name = name;
        this.value = value;
        this.leftChild = leftChild;
        this.rightChild = rightChild;
    }

    @Override
    public String toString() {
        return "HuffmaNode [name=" + name + ", value=" + value + ", encode=" + encode + "]";
    }

}
package com.newer.tree;
/**
 *           我的哈弗曼树
 * 什么是哈弗曼树:哈弗曼树是最优二叉树,树的带权路径长度最小的一个二叉树。
 * 带权路径长度为根节点到该节点的路径长度和该节点权重的乘积。
 * 路径长度为当前节点到另一个节点所经过的分支的个数(边的个数)。
 * 
 * 应用场景:哈弗曼树可以用来求哈弗曼编码,通过对文件中不同数据出现的频率,
 * 设计出新的编码方式,来对文件进行数据压缩。
 * 建立哈弗曼树:
 * 1.将表示不同数据的节点按照出现的频率(权重)进行排序。
 * 2.选取出两个最小频率(权重)的数据,创建新节点,作为新节点的两个子节点。
 * 3.将两个子节点从原有的节点集删除,计算新节点的权重,并将其加入到节点集合中。
 * 4.对新的节点集进行排序,重复2和3步骤,直到节点集中只有一个节点。
 *        
 * @author lixiaochi
 *
 */
public class MyHuffmanTree {
    // 哈弗曼树的根节点
    HuffmaNode root;
    
    public static void main(String[] args) {
        MyHuffmanTree huffmantree = new MyHuffmanTree();
        // 数组中的元素是一个节点,节点中有数据内容和出现的频率。
        HuffmaNode[] nodeArray = new HuffmaNode[6];
        // 哈弗曼树中各个节点的初始化。
        nodeArray[0]=new HuffmaNode("A",27);
        nodeArray[1]=new HuffmaNode("B",8);
        nodeArray[2]=new HuffmaNode("C",15);
        nodeArray[3]=new HuffmaNode("D",15);
        nodeArray[4]=new HuffmaNode("E",30);
        nodeArray[5]=new HuffmaNode("F",5);
        
        // 创建一颗哈弗曼树
        huffmantree.root = huffmantree.create(nodeArray);
        
        // 对哈弗曼树进行编码,其实可以在生成哈弗曼树的时候,一起生成哈弗曼编码。
        encode(huffmantree.root);
        
        // 按先序的方式输出哈弗曼树的每个节点的信息。
        print(huffmantree.root);
        
    }
    
    public static HuffmaNode create(HuffmaNode[] nodeArray)  {
        
        // 表示当前要排序的起始位置
        int num = 0;
        
        // 不断循环,一直到节点集只有一个节点。
        while(num<nodeArray.length-1)  {
            // 对当前节点集进行排序,使用了最简单的选择排序。
            // 可以使用高效的排序方法,快排,归排都可以。
            for(int i=num;i<nodeArray.length;i++)  {
                int min=i;  
                for(int j=i+1;j<nodeArray.length;j++)  {
                    if(nodeArray[j].value<nodeArray[min].value)  {
                        min=j;
                    }
                }
                swap(nodeArray,i,min);
            }
            
            // 创建新节点,记录新节点的权重
            int newNodeValue = nodeArray[num].value+nodeArray[num+1].value;
            HuffmaNode newNode = new HuffmaNode("分支节点",newNodeValue,nodeArray[num],nodeArray[num+1]);
            // 将节点加入到节点集中,这里的num表示的起始位置,已经实现了在节点集数组中删除两个节点。
            nodeArray[++num] = newNode;
        }
        return nodeArray[num];
    }

    private static void swap(HuffmaNode[] nodeArray, int i, int min) {
        HuffmaNode temp = nodeArray[i];
        nodeArray[i] = nodeArray[min];
        nodeArray[min] = temp;
    }  
    
    public static void encode(HuffmaNode node)  {
        encode(node,"0","1","");
    }
    
    // 对哈弗曼树中叶子节点进行编码。
    public static void encode(HuffmaNode node,String a,String b,String c)  {
        if(node.leftChild != null)  {
            String temp = c+"0";
            encode(node.leftChild,"0","1",temp);
        }
        if(node.rightChild != null)  {
            String temp = c+"1";
            encode(node.rightChild,"0","1",temp);
        }
        if(node.leftChild==null && node.rightChild==null)  {
            node.encode=c;
        }
        
    }
    
    // 按先序的方式输出哈弗曼树的每个节点的信息。
    public static void print(HuffmaNode node)  {
        if(node != null)  {
            System.out.println(node);
            print(node.leftChild);
            print(node.rightChild);
        }
    }
    
}

显示结果

 

以上是关于Java---Huffman树的实现的主要内容,如果未能解决你的问题,请参考以下文章

Java- 哈夫曼(Huffman)压缩算法

Huffman树的构造及编码与译码的实现

深夜爆肝:万字长文3种语言实现Huffman树(强烈建议三连)

深夜爆肝:万字长文3种语言实现Huffman树(强烈建议三连)

二叉树的基本操作(含Huffman树)

Huffman的应用之文件压缩与解压缩