数据结构实验哈夫曼编码

先构建一个结点类,其结构中包含有权值、双亲值、左孩子、右孩子、角标和Huffman编码。将数组里的数据,利用顺序表实现存储,调用Collections集合存放数据,调用其sort方法实现排序。然后选取其中最小的两个子树进行建立Huffman树。逆序计算Huffman编码,一次球1~n个结点对应的编码。建立一个临时存储Huffman编码的字符的数组,从的一个结点开始,通过该结点找到其双亲,若该结点是双亲的左孩子,则向数组输入为“0”,若是右孩子,则输入“1”。将临时数组中的值逆序输入到所求结点对应的二维数组中的那一行。这样就得到了所有结点的Huffman编码。

源码如下


public class Haff {
    public static int number;
    static List<Node> list;

    public static void main(String[] args) {

        list = new ArrayList<Node>();
        out.println("请输入个数:");
        Scanner scanner = new Scanner(System.in);
        number = scanner.nextInt();
        out.println("请输入权值:");
        int[] wightness = new int[number];
        for (int i = 0; i < wightness.length; ++i) {
            wightness[i] = scanner.nextInt();
        }
        for (int i = 0; i < number; ++i) {
            Node node = new Node(wightness[i], i);
            list.add(node);
        }
        Collections.sort(list);
        huffmanTree();
    }

    private static ArrayList<Integer> selectTwoMin() {
        ArrayList<Integer> List = new ArrayList<Integer>();
        Integer first = 0, second = 0;/* 两个最小值都初始化为下表为0 */
        double small1, small2;
        small1 = small2 = Double.MAX_VALUE;/* 将最大值和最小值初始化为double类型的最大值 */
        for (int i = 0; i < list.size(); ++i) {
            if (list.get(i).parent == -1) {
                if (small1 > list.get(i).weight) {
                    second = first;/* 更新次小的值 */
                    small2 = small1;
                    small1 = list.get(i).weight;/* 更新最小值 */
                    first = i;
                } else if (small2 > list.get(i).weight) {
                    small2 = list.get(i).weight;/* 更新次小值 */
                    second = i;
                }
            }
        }
        List.add(first);
        List.add(second);
        return List;
    }


    public static void huffmanTree() {

        for (int i = number; i < 2 * number - 1; i++) {
            ArrayList<Integer> min = selectTwoMin();
            Integer first = min.get(0);
            Integer second = min.get(1);
            Node left = list.get(first);
            Node right = list.get(second);
            left.setParent(i);
            right.setParent(i);
            Node parent = new Node(left.weight+right.weight,i);
            parent.setLchild(list.get(first).index);
            parent.setRchild(list.get(second).index);
            list.add(parent);

        }

        for (Node node : list) {
            node.huffmanCode(list);
            node.show();
        }
    }
}
public class Node implements Comparable<Node> {
    public int parent;
    private int lchild;
    private int rchild;
    public double weight;
    public int index;
    public String code;

    public Node(double weight, int index) {
        super();
        this.weight = weight;
        this.index = index;
        this.parent = -1; // 父节点初始化为-1,代表没有父节点
        this.lchild = -1; // 左孩子初始化为-1,代表没有左孩子
        this.rchild = -1; // 右结点初始化为-1,代表没有右孩子
        this.code = "";
    }

    public int compareTo(Node o) {
        if(this.weight < o.weight)
            return -1;
        else if(this.weight > o.weight)
            return 1;
        return 0;
    }


    public void show() {
        out.println("index  wight  rchild  lchild  code");
        out.println(index+"      "+weight+"      "+rchild+"      "+lchild+"     "+code);
    }

    public void setLchild(int lchild) {
        this.lchild = lchild;
    }

    public void setRchild(int rchild) {
        this.rchild = rchild;
    }

    public void setParent(int parent) {
        this.parent = parent;
    }

    public void huffmanCode(List<Node> list) {
        int parent = this.parent;
        int index = this.index;
        while (parent != -1) {	//结点的父节点为-1代表这个结点是根节点,树叶不断寻找父节点,由下向上求哈夫曼编码
            if (list.get(parent).lchild == index)
                code += "0";	//如果树叶是树叶父节点的左孩子
            else
                code += "1";

            index = list.get(parent).index;
            parent = list.get(parent).parent;
        }
        StringBuffer reverse = new StringBuffer();
        for (int i = code.length() - 1; i >= 0; --i)
            reverse.append(code.charAt(i));

        code = reverse.toString();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值