哈夫曼树讲解(最优二叉树)

X9-2、java数据结构---赫(霍)夫曼树【2021-1-3】 - 简书 (jianshu.com)

1.创建哈夫曼树的思路重点

 

 其实思路就是 每次拿出两个最小值的结点作为根节点  再合成一个新的结点 然后去掉使用的两个结点 把新的结点加入到数组里面

结点的权值较小的一个总是在左子结点

全部代码


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

/**
 * title: 赫夫曼树实现
 * @author 阿K
 * 2021年1月3日 下午5:43:07
 */
public class HuffmanTree {

    public static void main(String[] args) {

        int arr[] = { 13, 7, 8, 3, 29, 6, 1 };
        Node root = createHuffmanTree(arr);

        System.out.println("---------美丽的分割线-----------");
        // 测试
        preOrder(root);
    }

    // 前序遍历
    public static void preOrder(Node root) {
        if(root!=null) {
            root.preOrder();
        }else {
            System.out.println("改二叉树为空,前序遍历的鸡毛??");
        }
    }

    /**
     * 创建赫夫曼树
     *
     * @param arr 需要被构建成的数组
     * @return 返回 赫夫曼树 的 root节点
     */
    public static Node createHuffmanTree(int[] arr) {
        // 【1】将要数组转换为节点
        // (1)遍历arr数组
        // (2)将arr数组的每个元素构建成 Node
        // (3)将 所有 Node 放入 ArrayList 中
        List<Node> nodes = new ArrayList<>();
        for (int value : arr) {
            nodes.add(new Node(value));
        }

        // 【2】循环处理分析得四步骤,故,最终返回的只有一个 root 节点
        while (nodes.size() > 1) {// 逐步递减,直到只有一个节点为止(既root
            // 1、从小到大排序(每次循环都要排序一次)
            Collections.sort(nodes);

            System.out.println("nodes =" + nodes);

            // 2、取出根节点权值最小的两颗二叉树,然后合并
            // <1> 取出权值最小的节点(二叉树)
            Node leftNode = nodes.get(0);
            // <2> 取出权值次小(第二小)的节点(二叉树)
            Node rightNode = nodes.get(1);
            // <3> 合并成一颗新的二叉树
            Node parent = new Node(leftNode.value + rightNode.value);
            parent.left = leftNode;
            parent.rigth = rightNode;

            // 3、从 nodes 集合中删除已经处理过的二叉树
            nodes.remove(leftNode);
            nodes.remove(rightNode);

            // 4、将 合并出来的二叉树 parent 加入到 nodes集合中
            nodes.add(parent);
        }

        // 【3】返回赫夫曼树的 root 节点
        return nodes.get(0);
    }

}

// 节点类
// 实现Comparable接口排序
class Node implements Comparable<Node> {

    int value; // 节点权值
    Node left; // 指向左子节点
    Node rigth; // 指向右子节点

    public Node(int value) {
        super();
        this.value = value;
    }

    // 前序遍历
    public void preOrder() {
        System.out.println(this);

        if (this.left != null) {
            this.left.preOrder();
        }

        if (this.rigth != null) {
            this.rigth.preOrder();
        }
    }

    @Override
    public int compareTo(Node o) {
        // 表示从小到大排序
        return this.value - o.value;
    }

    @Override
    public String toString() {
        return "Node [value=" + value + "]";
    }

}

在创建哈夫曼树的时候 有一个额外的步骤  就是根据结点的权值进行排序  所以Node类需要实现Comparable方法

 
// 节点类
// 实现Comparable接口排序
class Node implements Comparable<Node> {//这个就是实现接口  实现了这个接口必须重新它里面的一个方法才行 也就是compareto方法

    int value; // 节点权值
    Node left; // 指向左子节点
    Node rigth; // 指向右子节点

    public Node(int value) {
        super();
        this.value = value;
    }

    // 前序遍历
    public void preOrder() {
        System.out.println(this);

        if (this.left != null) {
            this.left.preOrder();
        }

        if (this.rigth != null) {
            this.rigth.preOrder();
        }
    }

    @Override
    public int compareTo(Node o) {
        // 表示从小到大排序  升序
        return this.value - o.value;
       // return  o.value-this.value  这个是降序
    }

    @Override
    public String toString() {
        return "Node [value=" + value + "]";
    }

}

创建的步骤;
1.先创建一个数组  因为我们是根据数组创建哈夫曼树的(main函数里面)

现在开始讲解哈夫曼树里面的代码

数组里面的每一个元素就对应一个结点

因为有很多个结点 所以要存起来  因为结点是按权值的顺序大小排的 所以用List有序集合

 

 我们把断点打在这里  不要打在for循环 因为这不是主要步骤 主要步骤是怎么创建 而不是看怎么把结点装入集合的过程

 

开始调试后 此时的值

 

疯狂点击下一步 就进入到了这里

此时的值 

 图示的arr似乎没排序 其实已经变化了的  因为变化的是list集合 而不是arr数组

只有重写了compareto方法的类才能使用这个sort方法

 

 

这个就仅仅是单纯的打印结点 看看排序成功否

然后再向下执行

 

 

经过了这两步  (这两步很好理解 就不做解释了)

 

此时的值

 然后再疯狂按下一步

 经过了这两步(这两部也不做解释了)

 此时的值

 此时的二叉树就变成了这样   集合里面的值是这些 4 6  7 8 13 29

 再疯狂点下一步

 这几步也就是做了这些工作 

原本的数组

创建了这个二叉树后的数组 4 6 7 8 13 29

 

 

 再点击下一步 就会再进入while循环

 然后做重复的工作 

直到size变成1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值