Java解决算法-霍夫曼编码

import java.util.ArrayList;

import java.util.Collections;

import java.util.Iterator;

/** 霍夫曼编码

 * table = new int[][] { { 0, 0, 0, 0, 0, 0, 0 },

                       { 'a', 7, 0, 0, 0, 0, 0 },

                       { 'b', 0, 5, 0, 0, 0, 0 },

                      { 'c', 0, 0, 3, 0, 0, 0 },

                      { 'd', 0, 0, 0, 2, 0, 0 },

                      { 'e', 0, 0, 0, 0, 12, 0 },

                      { 'f', 0, 0, 0, 0, 0, 9 } };

    二维数组里面第一列存放字符,字符对应行上放的是字符的频率或者出现次数

 * */

public class Task8_31 {

 

    private int[][] table;

    private ArrayList<Point> Ppoints;//一个点的序列,Point类在下面,实际上一个点就是一个二叉树

    private ArrayList<Point> huffmanTree;//我这里的 霍夫曼树 其实是个 对象数组,有五个元素,每个元素都保存着

                                         //构造  真正霍夫曼树的五个中间节点

    private String left = "1";

 

    /** 构造函数 */

    public Task8_31() {

       Ppoints = new ArrayList<Point>();

       huffmanTree = new ArrayList<Point>();

       huffman();

       Point point = huffmanTree.get(huffmanTree.size() - 1);

       System.out.println("各个字符的霍夫曼编码为:");

       huffamnCode(point);

    }

 

    /** 霍夫曼编码--使用递归,遍历霍夫曼树 */

    public void huffamnCode(Point point) {// 霍夫曼编码,树的遍历 使用递归遍历

       if (point.getLeftPoint() != null) {//算法设计很难,想了很久,断点debug了很久

           System.out.print(left + " "

                  + (char) Integer.parseInt(point.getLeftPoint().getName())

                  + "/n");

           left = "0" + left;

       }

       if (point.getRightPoint() != null) {

           huffamnCode(point.getRightPoint());

       }

       // if(point.getLeftPoint() == null ){//左子树空不空无所谓

       // System.out.print(left+"0"+(char)Integer.parseInt(point.getName())+"/n");

       // System.out.print(left+"1"+(char)Integer.parseInt(tempPoint.getRightPoint().getName())+"/n");

       // }

       if (point.getRightPoint() == null) {// 关键是右子树对空进行判断

           System.out.print(left.substring(0, left.length() - 1) + " "

                  + (char) Integer.parseInt(point.getName()) + "/n");

       }

    }

 

    /** 建造霍夫曼树 */

    public void huffman() {// 霍夫曼树已经建造出来了,可是霍夫曼编码怎么输出?--思考中。。。

       createTable();

       createPpoints();

       printPointsInfo();

       Point[] points = findTheLowestTwoPoints();

       huffmanTree.add(new Point("1", points[0], points[0].getWeight()

              + points[1].getWeight(), points[1]));

       Ppoints.remove(0);

       Ppoints.remove(0);

       int timer = Ppoints.size();

       int ref = 0;

       while (timer > 0) {

           Point point = Ppoints.get(0);

           huffmanTree.add(new Point("1", point, point.getWeight()

                  + huffmanTree.get(ref).getWeight(), huffmanTree.get(ref)));

           timer--;

           ref++;

           Ppoints.remove(0);

       }

    }

   

    public void printPointsInfo(){

       Iterator<Point> it = Ppoints.iterator();

       while(it.hasNext()){

           System.out.println(it.next());

       }

    }

   

 

    /** 建表 */

    public void createTable() {

       table = new int[][] { { 0, 0, 0, 0, 0, 0, 0 },

              { 'a', 7, 0, 0, 0, 0, 0 }, { 'b', 0, 5, 0, 0, 0, 0 },

              { 'c', 0, 0, 3, 0, 0, 0 }, { 'd', 0, 0, 0, 2, 0, 0 },

              { 'e', 0, 0, 0, 0, 12, 0 }, { 'f', 0, 0, 0, 0, 0, 9 } };

    }

 

    /** 二叉树的构造,二叉树抽象为两颗子树为null的点 */

    public void createPpoints() {

       for (int i = 1; i < table.length; i++)

           if (table[i][i] > 0) {

              Ppoints.add(new Point(table[i][0] + "", null, table[i][i], null));

           }

    }

 

    /** 返回点中权值最小的两个二叉树 */

    @SuppressWarnings("unchecked")

    public Point[] findTheLowestTwoPoints() {

       Collections.sort(Ppoints);

       return new Point[] { Ppoints.get(0), Ppoints.get(1) };

    }

 

    /** 主函数 */

    public static void main(String[] args) {

       new Task8_31();

    }

}

 

/** 二叉树类 */

@SuppressWarnings("rawtypes")

class Point implements Comparable {// 实现Comparable接口,以便于排序

 

    private String name = "";// 保存字符名称

    private int weight = 0;// 保存权值

    private Point leftPoint = null;// 左孩子

    private Point rightPoint = null;// 右孩子

 

    public String getName() {

       return name;

    }

 

    public void setName(String name) {

       this.name = name;

    }

 

    public int getWeight() {

       return weight;

    }

 

    public void setWeight(int weight) {

       this.weight = weight;

    }

 

    public Point getLeftPoint() {

       return leftPoint;

    }

 

    public void setLeftPoint(Point leftPoint) {

       this.leftPoint = leftPoint;

    }

 

    public Point getRightPoint() {

       return rightPoint;

    }

 

    public void setRightEdge1(Point rightPoint) {

       this.rightPoint = rightPoint;

    }

 

    public Point() {

 

    }

    /** 构造*/

    public Point(String name, Point leftPoint, int weight, Point rightPoint) {

       this.weight = weight;

       this.leftPoint = leftPoint;

       this.rightPoint = rightPoint;

       this.name = name;

    }

 

    @Override

    public int compareTo(Object o) {

       if (((Point) o).weight > this.weight)

           return -1;

       else if (((Point) o).weight == this.weight)

           return 0;

       else

           return 1;

    }

 

    public String toString() {

       return "点:" + (char) Integer.parseInt(name) + " " + leftPoint + " "

              + weight + " " + rightPoint;

    }

}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值