哈夫曼树和哈夫曼编码的java实现

本文详细介绍了Java中的HuffmanNode和HuffmanTree2类,展示了如何构建Huffman树以及如何通过节点的权重生成哈夫曼编码,以优化数据压缩过程。
摘要由CSDN通过智能技术生成

下面是节点类:

public class HuffmanNode <T>{
    private T data;
    public double weight;
    public int parent;
    public int lChild;
    public int rChild;
    public String huffmanCode;  // 新增字段用于存储哈夫曼编码

    public HuffmanNode(){
        this.data= null;
        this.weight= 0;
        this.parent= 0;
        this.lChild= -1;
        this.rChild= -1;
    }

    public HuffmanNode(T x, double w){
        data= x;
        weight= w;
        parent= 0;
        lChild= -1;
        rChild= -1;
    }

    public T getData(){
        return data;
    }
}

下面是哈夫曼树的构造以及哈夫曼编码方法:

public class HuffmanTree2<T> {
    private final int maxSize = 100;
    private HuffmanNode<T>[] nodes;
    public int length;

    public HuffmanTree2() {
        nodes = new HuffmanNode[maxSize];
        length = 0;
    }

    private int selectMin() {
        int t = -1;

        // 寻找第一个未被选择的节点
        for (int i = 0; i < this.length; i++) {
            if (nodes[i].parent == 0) {
                t = i;
                break;
            }
        }

        // 寻找未被选择的、权重最小的节点
        for (int i = 0; i < this.length; i++) {
            if (nodes[i].parent == 0 && nodes[i].weight < nodes[t].weight) {
                t = i;
            }
        }

        if (t != -1) {
            nodes[t].parent = 1;
            return t;
        }

        return -1; // 如果所有节点都已被选择,则返回-1
    }

    public void buildHuffmanTree() {
        int first = -1;
        int second = -1;

        do {
            first = selectMin();
            second = selectMin();
            if (second != -1) {
                double weight = nodes[first].weight + nodes[second].weight;
                HuffmanNode<T> node = new HuffmanNode<>(null, weight);
                node.lChild = first;
                node.rChild = second;
                nodes[length] = node;
                nodes[first].parent = length;
                nodes[second].parent = length;
                length++;
            }
        } while (second != -1);
        nodes[length - 1].parent = 0;

    }


    public void huffmanCoding(){
        for (int i = 0; i < this.length; i++) {
            int current = i;
            int father = this.nodes[i].parent;
            String t = "";

            while (father != 0) {
                if (this.nodes[father].lChild == current) {
                    t = "0" + t;  // 从高位到低位记录路径
                } else {
                    t = "1" + t;  // 从高位到低位记录路径
                }

                current = father;
                father = this.nodes[father].parent;
            }

            this.nodes[i].huffmanCode = t;
        }
    }


    public static void main(String[] args) {
        HuffmanTree2<Character> huffmanTree = new HuffmanTree2<>();

        // 初始化一些节点
        huffmanTree.nodes[huffmanTree.length++] = new HuffmanNode<>('A', 10);
        huffmanTree.nodes[huffmanTree.length++] = new HuffmanNode<>('B', 15);
        huffmanTree.nodes[huffmanTree.length++] = new HuffmanNode<>('C', 12);
        huffmanTree.nodes[huffmanTree.length++] = new HuffmanNode<>('D', 3);
        huffmanTree.nodes[huffmanTree.length++] = new HuffmanNode<>('E', 4);

        huffmanTree.buildHuffmanTree();
        huffmanTree.huffmanCoding();

        System.out.println("哈夫曼树构造:");
        for (int i = 0; i < huffmanTree.length; i++) {
            System.out.println("Node " + i + ": Data=" + huffmanTree.nodes[i].getData() +
                    ", Weight=" + huffmanTree.nodes[i].weight +
                    ", Parent=" + huffmanTree.nodes[i].parent +
                    ", Left Child=" + huffmanTree.nodes[i].lChild +
                    ", Right Child=" + huffmanTree.nodes[i].rChild);
        }

        System.out.println("哈夫曼编码:");
        for (int i = 0; i < huffmanTree.length; i++) {
            System.out.println("Character: " + huffmanTree.nodes[i].getData() +
                    " Weight: " + huffmanTree.nodes[i].weight +
                    " Huffman Code: " + huffmanTree.nodes[i].huffmanCode);
        }
    }
}

主函数可以自己修改,是一些测试用的节点。

HuffmanNode类:

HuffmanNode类定义了Huffman树的节点,每个节点包含数据、权重、父节点索引、左子节点索引和右子节点索引。初始时,节点的父节点和子节点索引设置为特殊值表示未连接。

HuffmanTree2类:

字段:
  • maxSize:最大树大小,这里设置为常量100。
  • nodes:存储Huffman节点的数组。
  • length:当前树中节点的数量。
构造方法:

构造方法初始化nodes数组和length计数器。

selectMin方法:

selectMin方法选择未被选择的、权重最小的节点。首先找到第一个未被选择的节点,然后在剩余未选择的节点中找到权重最小的节点,并将其标记为已选择。

buildHuffmanTree方法:

buildHuffmanTree方法构建Huffman树。它重复选择两个最小权重的节点,合并它们成为新节点,然后添加到数组中,直到只剩下一个节点。构建过程中更新父节点和子节点的关系。

哈夫曼编码方法:

  1. 遍历每个节点: 使用 for 循环遍历哈夫曼树的每个节点。this.length 可能表示哈夫曼树中节点的个数。

  2. 初始化当前节点和父节点: 对于每个节点,初始化当前节点 current 为当前循环的节点的索引,初始化父节点 father 为当前节点的父节点的索引。

  3. 循环生成编码: 进入 while (father != 0) 循环,该循环用于从当前节点一直追溯到根节点,生成哈夫曼编码。

    • 在循环中,判断当前节点是其父节点的左子节点还是右子节点。

    • 如果是左子节点,将字符 '0' 添加到 t 的前面。

    • 如果是右子节点,将字符 '1' 添加到 t 的前面。

    • 更新 current 为父节点,father 为新的父节点,继续追溯。

  4. 保存哈夫曼编码: 将生成的哈夫曼编码 t 赋值给当前节点的 huffmanCode 属性。

整体来说,这个方法是通过迭代从叶子节点向上追溯到根节点,生成每个节点的哈夫曼编码。由于哈夫曼编码是从根节点到叶子节点的路径编码,所以从叶子节点向上追溯能够正确地构建每个节点的编码。生成的编码会保存在每个节点的 huffmanCode 属性中,最终完成哈夫曼编码的生成过程。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值