算法导论示例-Huffman

原创 2006年06月21日 00:46:00
/**
 * Introduction to Algorithms, Second Edition 
 * 16.3 Huffman codes 
 * 
 * @author 土豆爸爸
 * 
 */
import java.util.List;

public class Huffman {
    static class Node implements IPriorityQueueElement<Integer>{
        Node left; //左子节点
        Node right; //右子节点
        Integer f; //频率
        char c; //字符
        
        public Node() {}
        
        public Node(char c, Integer f) {
            this.c = c;
            this.f = f;
        }
        public Integer getKey() {
            return f;
        }
    }
    
    public static Node encode(List<Node> nodes) {
        int n = nodes.size();
        
        //根据频率生成最小优先队列
        MinPriorityQueue<Integer, Node> queue = new MinPriorityQueue<Integer, Node>(n);
        for(Node node : nodes) {
            queue.insert(node);
        }
        
        for(int i = 0; i < n - 1; i++) {
            Node node = new Node();
            Node x = queue.extractMin(); //取出队列的前两个元素
            Node y = queue.extractMin();
            node.left = x; //将取出两个元素作为新节点的子节点
            node.right = y;
            node.f = x.f + y.f; //新节点的频率是子节点频率之和
            queue.insert(node); //插入到队列中
        }
        
        return queue.extractMin();
    }
}

/**
 * Introduction to Algorithms, Second Edition 
 * 6.5 min-priority queue 
 * 
 * @author 土豆爸爸
 * 
 */
import java.util.EmptyStackException;

public class MinPriorityQueue<KeyType extends Comparable<KeyType>, T extends IPriorityQueueElement<KeyType>> {
    T[] array;

    int heapSize;

    /**
     * 构造函数
     * @param size 初始数组大小
     */
    @SuppressWarnings("unchecked")
    public MinPriorityQueue(int size) {
        array = (T[]) new IPriorityQueueElement[size];
    }

    /**
     * 获取当前heap中的最小值
     * 
     * @return 最小值
     */
    public T minimum() {
        return array[0];
    }

    /**
     * 获取当前heap中的最小值,并从heap中删除最小值
     * @return 最小值
     */
    public T extractMin() {
        if (heapSize < 1) {
            throw new EmptyStackException();
        }
        T min = array[0];
        array[0] = array[heapSize - 1];
        heapSize--;
        minHeapify(0);
        return min;
    }

    /**
     * 插入一个元素
     * @param e
     */
    @SuppressWarnings("unchecked")
    public void insert(T e) {
        if (heapSize == array.length) {
            T[] newArray = (T[]) new IPriorityQueueElement[array.length * 2];
            System.arraycopy(array, 0, newArray, 0, array.length);
            array = newArray;
        }
        int i = heapSize++;
        array[i] = e;
        int p = parent(i); // 父结点索引
        while (i > 0 && array[p].getKey().compareTo(array[i].getKey()) > 0) {
            T temp = array[i];
            array[i] = array[p];
            array[p] = temp;
            i = p;
            p = parent(i);
        }
    }

    /**
     * 使数组的第i个元素按max heap规则重排
     * 
     * @param i
     *            元素索引
     */
    private void minHeapify(int i) {
        int l = left(i);
        int r = right(i);
        int smallest; // 当前结点/左子结点/右子结点中最大值的索引
        if (l < heapSize && array[l].getKey().compareTo(array[i].getKey()) < 0) {
            smallest = l;
        } else {
            smallest = i;
        }

        if (r < heapSize && array[r].getKey().compareTo(array[smallest].getKey()) < 0) {
            smallest = r;
        }

        if (smallest != i) {
            // 如果最大值不是当前结点,进行交换
            T temp = array[i];
            array[i] = array[smallest];
            array[smallest] = temp;
            // 递归调用,直到当前结点比其子结点大
            minHeapify(smallest);
        }

    }

    /**
     * 计算结点索引为i的元素的父结点的索引
     * 
     * @param i
     *            当前索引
     * @return 父结点的索引
     */
    private int parent(int i) {
        return (i + 1) / 2 - 1;
    }

    /**
     * 计算结点索引为i的元素的左子结点的索引
     * 
     * @param i
     *            当前索引
     * @return 左子结点的索引
     */
    private int left(int i) {
        return 2 * i + 1;
    }

    /**
     * 计算结点索引为i的元素的右子结点的索引
     * 
     * @param i
     *            当前索引
     * @return 右子结点的索引
     */
    private int right(int i) {
        return 2 * i + 2;
    }
}

public interface IPriorityQueueElement<KeyType extends Comparable<KeyType>>{
    KeyType getKey();
}

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

import junit.framework.TestCase;

public class HuffmanTest extends TestCase {
    public void testEncode() {
        List<Huffman.Node> c = new ArrayList<Huffman.Node>();
        c.add(new Huffman.Node('a', 45));
        c.add(new Huffman.Node('b', 13));
        c.add(new Huffman.Node('c', 12));
        c.add(new Huffman.Node('d', 16));
        c.add(new Huffman.Node('e', 9));
        c.add(new Huffman.Node('f', 5));
        
        Huffman.Node root = Huffman.encode(c);
        assertEquals(100, root.f.intValue());
        assertEquals(45, root.left.f.intValue());
        assertEquals('a', root.left.c);
        assertEquals(55, root.right.f.intValue());
        assertEquals('c', root.right.left.left.c);
        assertEquals('b', root.right.left.right.c);
        assertEquals('f', root.right.right.left.left.c);
        assertEquals('e', root.right.right.left.right.c);
        assertEquals('d', root.right.right.right.c);
    }
}

Huffman编码示例代码

// Huffman编码示例代码 struct HuffmanNode { int nFrequency; // 频率 struct HuffmanNode* pParent; // 父节点 ...
  • iicup
  • iicup
  • 2014年04月18日 00:00
  • 671

huffman 编码示例程序

本人开发环境为VS2013。 如图1所示:本程序是对0-255这256个符号进行编码 图1. HUFF_ENC.C程序中的注释部分 因此,我选择了一幅yuv格式图像进行编码,为了方便观察编码后...
  • chenyangming1994
  • chenyangming1994
  • 2017年03月21日 09:11
  • 109

Huffman编码解码

转载自:http://blog.csdn.net/q547550831/article/details/51589278 Huffman编码解码 霍夫曼(Huffman)编码问题也...
  • riba2534
  • riba2534
  • 2017年04月20日 21:08
  • 532

数据结构和算法——Huffman树和Huffman编码

Huffman树是一种特殊结构的二叉树,由Huffman树设计的二进制前缀编码,也称为Huffman编码在通信领域有着广泛的应用。在word2vec模型中,在构建层次Softmax的过程中,也使用到了...
  • google19890102
  • google19890102
  • 2017年02月04日 15:43
  • 1528

Huffman编码与解码_C语言实现

哈夫曼编码(Huffman Coding),是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的...
  • vacu_um
  • vacu_um
  • 2017年04月16日 10:22
  • 1452

huffman编解码实现(C语言实现版本)

/* * huffman - Encode/Decode files using Huffman encoding. * Copyright (C) 2003 Douglas Ryan ...
  • zixie1991
  • zixie1991
  • 2013年12月20日 10:31
  • 1834

Huffman 压缩解压缩java实现

本文介绍了利用Huffman编码对文件进行压缩和解压缩的过程。其中使用了java做为编程语言。为大家提供参考。本文只实现了对文本文件进行压缩和解压缩,对二进制文件压缩解压缩留待大家研究。完整工程留待以...
  • u010485034
  • u010485034
  • 2014年06月14日 16:14
  • 1853

Huffman编码原理详解

1、概述      huffman编码是一种可变长编码(  VLC:variable length coding))方式,于1952年由huffman提出。依据字符在需要编码文件中出现的概率提供...
  • yang6464158
  • yang6464158
  • 2014年10月07日 11:38
  • 1931

Huffman编码解码

Huffman编码解码霍夫曼(Huffman)编码问题也就是最优编码问题,通过比较权值逐步构建一颗Huffman树,再由Huffman树进行编码、解码。其步骤是先构建一个包含所有节点的线性表,每次选取...
  • q547550831
  • q547550831
  • 2016年06月05日 14:06
  • 4281

多元Huffman编码问题

#include #include #include #include using namespace std;/* 每次选最小的k个元素进行合并。与2元Huffman算法类似 */...
  • u012319493
  • u012319493
  • 2015年11月25日 09:46
  • 1071
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:算法导论示例-Huffman
举报原因:
原因补充:

(最多只允许输入30个字)