zoukankan      html  css  js  c++  java
  • Java中的哈夫曼树

      1 package com.ietree.basic.datastructure.tree;
      2 
      3 import java.util.ArrayDeque;
      4 import java.util.ArrayList;
      5 import java.util.List;
      6 import java.util.Queue;
      7 
      8 /**
      9  * Created by ietree
     10  * 2017/5/1
     11  */
     12 public class HuffmanTree {
     13 
     14     public static class Node<E> {
     15         E data;
     16         double weight;
     17         Node leftChild;
     18         Node rightChild;
     19 
     20         public Node(E data, double weight) {
     21             this.data = data;
     22             this.weight = weight;
     23         }
     24 
     25         public String toString() {
     26             return "Node[data=" + data + ", weight=" + weight + "]";
     27         }
     28     }
     29 
     30     public static void main(String[] args) {
     31 
     32         List<Node> nodes = new ArrayList<Node>();
     33         nodes.add(new Node("A", 40));
     34         nodes.add(new Node("B", 8));
     35         nodes.add(new Node("C", 10));
     36         nodes.add(new Node("D", 30));
     37         nodes.add(new Node("E", 10));
     38         nodes.add(new Node("F", 2));
     39 
     40         Node root = HuffmanTree.create(nodes);
     41         System.out.println(breadthFirst(root));
     42 
     43     }
     44 
     45     /**
     46      * 构造哈夫曼树
     47      *
     48      * @param nodes 节点集合
     49      * @return 构造出来的哈夫曼树的根节点
     50      */
     51     private static Node create(List<Node> nodes) {
     52 
     53         // 只要nodes数组中还有2个以上的节点
     54         while (nodes.size() > 1) {
     55             quickSort(nodes);
     56             // 获取权值最小的两个节点
     57             Node left = nodes.get(nodes.size() - 1);
     58             Node right = nodes.get(nodes.size() - 2);
     59             // 生成新节点,新节点的权值为两个子节点的权值之和
     60             Node parent = new Node(null, left.weight + right.weight);
     61             // 让新节点作为权值最小的两个节点的父节点
     62             parent.leftChild = left;
     63             parent.rightChild = right;
     64             // 删除权值最小的两个节点
     65             nodes.remove(nodes.size() - 1);
     66             nodes.remove(nodes.size() - 1);
     67             // 将新生成的父节点添加到集合中
     68             nodes.add(parent);
     69         }
     70         // 返回nodes集合中唯一的节点,也就是根节点
     71         return nodes.get(0);
     72     }
     73 
     74     // 将指定数组的i和j索引处的元素交换
     75     private static void swap(List<Node> nodes, int i, int j) {
     76         Node tmp;
     77         tmp = nodes.get(i);
     78         nodes.set(i, nodes.get(j));
     79         nodes.set(j, tmp);
     80     }
     81 
     82     // 实现快速排序算法,用于对节点进行排序
     83     private static void subSort(List<Node> nodes, int start, int end) {
     84 
     85         // 需要排序
     86         if (start < end) {
     87             // 以第一个元素作为分界值
     88             Node base = nodes.get(start);
     89             // i从左边搜索,搜索大于分界值的元素的索引
     90             int i = start;
     91             // j从右边搜索,搜索小于分界值的元素的索引
     92             int j = end - 1;
     93             while (true) {
     94                 // 找到大于分界值的元素的索引,或者i已经到了end处
     95                 while (i < end && nodes.get(++i).weight >= base.weight) ;
     96                 // 找到小于分界值的元素的索引,或者j已经到了start处
     97                 while (j > start && nodes.get(--j).weight <= base.weight) ;
     98                 if (i < j) {
     99                     swap(nodes, i, j);
    100                 } else {
    101                     break;
    102                 }
    103             }
    104             swap(nodes, start, j);
    105             // 递归左子树序列
    106             subSort(nodes, start, j - 1);
    107             // 递归右子树序列
    108             subSort(nodes, j + 1, end);
    109         }
    110     }
    111 
    112     public static void quickSort(List<Node> nodes) {
    113         subSort(nodes, 0, nodes.size() - 1);
    114     }
    115 
    116     // 广度优先遍历
    117     public static List<Node> breadthFirst(Node root) {
    118 
    119         Queue<Node> queue = new ArrayDeque<Node>();
    120         List<Node> list = new ArrayList<Node>();
    121         if (root != null) {
    122             // 将根元素入“队列”
    123             queue.offer(root);
    124         }
    125         while (!queue.isEmpty()) {
    126             // 将该队列的“队尾”的元素添加到List中
    127             list.add(queue.peek());
    128             Node p = queue.poll();
    129             // 如果左子节点不为null,将它加入“队列”
    130             if (p.leftChild != null) {
    131                 queue.offer(p.leftChild);
    132             }
    133             // 如果右子节点不为null,将它加入“队列”
    134             if (p.rightChild != null) {
    135                 queue.offer(p.rightChild);
    136             }
    137         }
    138         return list;
    139 
    140     }
    141 
    142 }
  • 相关阅读:
    下拉框Html.DropDownList 和DropDownListFor 的经常用法
    39个让你受益的HTML5教程
    RapeLay(电车之狼R)的结局介绍 (隐藏结局攻略)
    BP神经网络算法学习
    java实现第七届蓝桥杯取球博弈
    java实现第七届蓝桥杯剪邮票
    java实现第七届蓝桥杯剪邮票
    java实现第七届蓝桥杯剪邮票
    java实现第七届蓝桥杯剪邮票
    java实现第七届蓝桥杯抽签
  • 原文地址:https://www.cnblogs.com/Dylansuns/p/6792385.html
Copyright © 2011-2022 走看看