哈夫曼树(最优二叉树) - Java实现

简介

哈夫曼树(Huffman)树又称最优二叉树,是指对于一组带有确定权值的叶子结点所构造的具有带权路径长度最短的二叉树。从树中一个结点到另一个结点之间的分支构成了两结点之间的路径,路径上的分支个数称为路径长度二叉树的路径长度是指由根结点到所有叶子结点的路径长度之和。如果二叉树中的叶子结点都有一定的权值,则可将这一概念拓展:设二叉树具有n个带权值的叶子结点,则从根结点到每一个叶子结点的路径长度与该叶子结点权值的乘积之和称为二叉树路径长度,记做:
WPL = W1L1 + W2L2 + ...... + WnLn;

构建过程

① 对数据中出现过的元素各产生一个树叶节点,并赋予其出现的频率。
② 令N为T1和T2的父节点,其中T1和T2是出现频率最低的两个节点,令N的频率为T1和T2的频率之和
③ 消去两个节点,插入N节点,重复前面的步骤。
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

代码实现

HuffmanTree.java

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

public class HaffmanTree {

    private List<Node> nodes;
    private Node root;

    // 实现排序接口,添加结点自动排序,从小到大排序
    private static class Node implements Comparable<Node>{
        private int value;
        private Node left;
        private Node right;

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

        public Node getLeft() {
            return left;
        }

        public void setLeft(Node left) {
            this.left = left;
        }

        public Node getRight() {
            return right;
        }

        public void setRight(Node right) {
            this.right = right;
        }

        @Override
        public int compareTo(Node o) {
            return this.value - o.value;
        }
    }

    public HaffmanTree() {}

    public void bulidHaffmanTree(int[] arr) {
        nodes = new ArrayList<>();
        for (int i = 0; i < arr.length; i++) {
            nodes.add(new Node(arr[i]));
        }
        root = createHaffmanTree(nodes);
    }
    private Node createHaffmanTree(List<Node> nodes) {
        while (nodes.size() > 1) {
            // 排序,每次取最小的两个结点
            Collections.sort(nodes);

            // 获得权值最小的两个结点,左结点大于右结点
            Node leftChild = nodes.get(1);
            Node rightChild = nodes.get(0);

            // 生成新结点
            Node newNode = new Node(leftChild.value + rightChild.value);
            newNode.left = leftChild;
            newNode.right = rightChild;

            // 删除权值最小的两个结点
            nodes.remove(0);
            nodes.remove(0);

            // 将新结点加入到集合中
            nodes.add(newNode);
        }
        return nodes.get(0);
    }

    // 先序遍历
    public void preOrder() {
        preOrder(root);
    }
    private void preOrder(Node root) {
        ArrayDeque<Node> stack = new ArrayDeque<>();

        while (root != null || !stack.isEmpty()) {
            System.out.println(root.value);
            stack.push(root);
            root = root.left;
        }
        if (!stack.isEmpty()) {
            root = stack.pop();
            root = root.right;
        }
    }

    // 中序遍历
    public void inOrder() {
        preOrder(root);
    }
    private void inOrder(Node root) {
        ArrayDeque<Node> stack = new ArrayDeque<>();

        while (root != null || !stack.isEmpty()) {
            stack.push(root);
            root = root.left;
        }
        if (!stack.isEmpty()) {
            root = stack.pop();
            System.out.println(root.value);
            root = root.right;
        }
    }

    // 非递归后序遍历
    public void postOrder() {
        postOrder(root);
    }
    private void postOrder(Node root) {
        ArrayDeque<Node> stack = new ArrayDeque<>();
        Node cur = root;
        Node pre = null;

        while (cur != null || !stack.isEmpty()) {
            while (cur != null) {
                stack.push(cur);
                cur = cur.left;
            }
            cur = stack.peek();
            if (cur.right == null || cur.right == pre) {
                System.out.print(cur.value + " ");
                pre = cur;
                stack.pop();
                cur = null;
            } else {
                cur = cur.right;
            }
        }
    }

    // 层序遍历
    public void levelOrder() {
        levelOrder(root);
    }
    private void levelOrder(Node root) {
        ArrayDeque<Node> queue = new ArrayDeque<>();
        Node curr = root;

        if (curr == null)
            return;
        queue.add(curr);

        while (!queue.isEmpty()) {
            curr = queue.remove();
            System.out.print(curr.value + " ");
            if (curr.left != null)
                queue.add(curr.left);
            if (curr.right != null)
                queue.add(curr.right);
        }
    }

}

测试代码
HuffmanTreeTest.java

public class HaffmanTreeTest {
    public static void main(String[] args) {
        int arr[] = {13, 7, 8, 3, 29, 6, 1};
        HaffmanTree haffmanTree = new HaffmanTree();
        haffmanTree.bulidHaffmanTree(arr);
        haffmanTree.postOrder();
        System.out.println();
        haffmanTree.levelOrder();
    }
}
发布了120 篇原创文章 · 获赞 16 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_43327091/article/details/102932360