20182327 2019-2020 《程序设计与数据结构》哈夫曼编码测试报告

20182327 2019-2020 《程序设计与数据结构》哈夫曼编码测试报告

  • 课程:《程序设计与数据结构》
  • 班级: 1823
  • 姓名:赵天昊
  • 学号:20182327
  • 实验教师:王志强
  • 实验日期:2019年11月17日
  • 必修/选修: 必修

教材中的哈夫曼树

  • 1、在计算机数据处理中,哈夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符号出现机率的方法得到的,出现机率高的字母使用较短的编码,反之出现机率低的则使用较长的编码,这便使编码之后的字符串的平均长度、期望值降低,从而达到无损压缩数据的目的。
  • 2、例如,在英文中,e的出现机率最高,而z的出现概率则最低。当利用哈夫曼编码对一篇英文进行压缩时,e极有可能用一个比特来表示,而z则可能花去25个比特(不是26)。用普通的表示方法时,每个英文字母均占用一个字节,即8个比特。二者相比,e使用了一般编码的1/8的长度,z则使用了3倍多。倘若我们能实现对于英文中各个字母出现概率的较准确的估算,就可以大幅度提高无损压缩的比例。
  • 3、哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。树的路径长度是从树根到每一结点的路径长度之和,记为WPL=(W1XL1+W2XL2+W3XL3+...+WnXLn),N个权值Wi(i=1,2,...n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,...n)。可以证明哈夫曼树的WPL是最小的。

哈夫曼树及测试的实现

  • 参考教材java创建哈夫曼树和实现哈夫曼——java实现哈夫曼编码,尝试读懂代码的同时加入自己的理解。
  • 首先建立哈夫曼树的结点类【HuffmanNode】利用泛型实现结点,定义左子树,右子树,权值和编码。

    ```
    public class HuffmanTreeNode implements Comparable{
    protected int weight; // 权值
    protected HuffmanTreeNode left; // 左孩子
    protected HuffmanTreeNode right; // 右孩子
    protected HuffmanTreeNode parent; // 父结点
    protected char element;
    protected HuffmanTreeNode(int weight, char element, HuffmanTreeNode left, HuffmanTreeNode right, HuffmanTreeNode parent) {
    this.weight = weight;
    this.element = element;
    this.left = left;
    this.right = right;
    this.parent = parent;
    }
    @Override
    public int compareTo(HuffmanTreeNode o) {
    if (this.weight > o.weight)
    return 1;
    else if (this.weight < o.weight)
    return -1;
    else
    return 0;
    }

···

  • 编写以下代码读取txt文件中的字母,用于将字母转化成哈夫曼编码。

    ~~~
    public static void main(String[] args) throws IOException {
    File file = new File("C:\Users\12441\Desktop\game\input1.txt");
    Scanner scan = new Scanner(file);
    String s = scan.nextLine();
    System.out.println(s);
    int[] array = new int[26];
    for (int i = 0; i < array.length; i++) {
    array[i] = 0;
    }
    for (int i = 0; i < s.length(); i++) {
    char x = s.charAt(i);
    array[x - ‘a‘]++;
    ···

  • 编写【getEnCoding】类将读取的字母转化成为哈夫曼编码,并且规定左子树为0,右子树为1
 public String[] getEncoding() {
        ArrayList<HuffmanTreeNode> arrayList = new ArrayList();
        inOrder(root,arrayList);
        for (int i=0;i<arrayList.size();i++)
        {
            HuffmanTreeNode node = arrayList.get(i);
            String result ="";
            int x = node.element-'a';
            Stack stack = new Stack();
            while (node!=root)
            {
                if (node==node.parent.left)
                    stack.push(0);
                if (node==node.parent.right)
                    stack.push(1);
                node=node.parent;
            }
            while (!stack.isEmpty())
            {
                result +=stack.pop();
            }
            codes[x] = result;
        }
        return codes;
    }
    public HuffmanTreeNode getRoot() {
        return root;
    }
  • 最后编写实现类【Huffman】从input1.txt中读取信息,转化为哈夫曼编码后将哈夫曼编码放入output.txt中后完成测试
public class RunHuffmanTree {
    public static void main(String[] args) throws IOException {
        File file = new File("C:\\Users\\12441\\Desktop\\game\\input1.txt");
        Scanner scan = new Scanner(file);
        String s = scan.nextLine();
        System.out.println(s);
        int[] array = new int[26];
        for (int i = 0; i < array.length; i++) {
            array[i] = 0;
        }
        for (int i = 0; i < s.length(); i++) {
            char x = s.charAt(i);
            array[x - 'a']++;
        }
        System.out.println("打印各字母出现频率:");
        for (int i = 0; i < array.length; i++) {
            System.out.print((char) ('a' + i) + ":" + (double) array[i] / s.length() + " ");
        }
        HuffmanTreeNode[] huffmanTreeNodes = new HuffmanTreeNode[array.length];
        for (int i = 0; i < array.length; i++) {
            huffmanTreeNodes[i] = new HuffmanTreeNode(array[i], (char) ('a' + i), null, null, null);
        }

        HuffmanTree huffmanTree = new HuffmanTree(huffmanTreeNodes);
        System.out.println("打印各字母的编码");
        String[] codes = huffmanTree.getEncoding();
        for (int i = 0; i < codes.length; i++) {
            System.out.println((char) ('a' + i) + ":" + codes[i]);
        }
        //进行编码:
        String result = "";
        for (int i = 0; i < s.length(); i++) {
            int x = s.charAt(i) - 'a';
            result += codes[x];
        }
        System.out.println("编码结果:" + result);
        //写入文件
        File file1 = new File("C:\\Users\\12441\\Desktop\\game\\output.txt");
        FileWriter fileWriter = new FileWriter(file1);
        fileWriter.write(result);
        fileWriter.close();
        //从文件读取
        Scanner scan1 = new Scanner(file1);
        String s1 = scan1.nextLine();
        HuffmanTreeNode huffmanTreeNode = huffmanTree.getRoot();
        //进行解码
        String result2 = "";
        for (int i = 0; i < s1.length(); i++) {
            if (s1.charAt(i) == '0') {
                if (huffmanTreeNode.left != null) {
                    huffmanTreeNode = huffmanTreeNode.left;
                }
            } else {
                if (s1.charAt(i) == '1') {
                    if (huffmanTreeNode.right != null) {
                        huffmanTreeNode = huffmanTreeNode.right;
                    }
                }
            }
            if (huffmanTreeNode.left == null && huffmanTreeNode.right == null) {
                result2 += huffmanTreeNode.element;
                huffmanTreeNode = huffmanTree.getRoot();
            }
        }
        System.out.println("解码结果:" + result2);
        //写入文件
        File file2 = new File("C:\\Users\\12441\\Desktop\\game\\file2.txt");
        FileWriter fileWriter1 = new FileWriter(file1);
        fileWriter1.write(result2);
        // 判断解码后原来是否一致
        System.out.println("编码解码后原来是否一致:" + result2.equals(s));
    }

}

实验结果


  • https://gitee.com/besti1823/2012_327_zhao_tianhao.git

原文地址:https://www.cnblogs.com/kv888777/p/11895572.html

时间: 2024-11-07 04:56:46

20182327 2019-2020 《程序设计与数据结构》哈夫曼编码测试报告的相关文章

(编程训练)再回首,数据结构——哈夫曼编码的实现

最近在复习数据结构,顺便看看大一的时候写的代码,看完之后比当初有了更加深刻的体会. 希望这些能提供给初学者一些参考. 在VC++6.0下可运行,当初还写了不少注释. [问题描述] 根据给定字符的使用频率,为其设计哈夫曼编码 [基本要求] ·功能:求出n个字符的哈夫曼编码 ·输入:输入n个字符和字符在电文中的使用频率 ·输出:n个字符的哈夫曼编码 [模块划分] 1.    初始化哈夫曼树函数 InitHuffmanTree() 2.    输入权值函数 InputWeight() 3.    选择

【数据结构】树与树的表示、二叉树存储结构及其遍历、二叉搜索树、平衡二叉树、堆、哈夫曼树与哈夫曼编码、集合及其运算

1.树与树的表示 什么是树? 客观世界中许多事物存在层次关系 人类社会家谱 社会组织结构 图书信息管理 分层次组织在管理上具有更高的效率! 数据管理的基本操作之一:查找(根据某个给定关键字K,从集合R 中找出关键字与K 相同的记录).一个自然的问题就是,如何实现有效率的查找? 静态查找:集合中记录是固定的,没有插入和删除操作,只有查找 动态查找:集合中记录是动态变化的,除查找,还可能发生插入和删除 静态查找--方法一:顺序查找(时间复杂度O(n)) int SequentialSearch(St

SDUT 3345 数据结构实验之二叉树六:哈夫曼编码

数据结构实验之二叉树六:哈夫曼编码 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 字符的编码方式有多种,除了大家熟悉的ASCII编码,哈夫曼编码(Huffman Coding)也是一种编码方式,它是可变字长编码.该方法完全依据字符出现概率来构造出平均长度最短的编码,称之为最优编码.哈夫曼编码常被用于数据文件压缩中,其压缩率通常在20%-90%之间.你的任务是对从键盘输入的一个字符串求出它的ASCII编码长度和哈夫曼

【数据结构与算法】二叉树——哈夫曼编码

最近有很多的小朋友问我什么是哈夫曼编码,哈夫曼编码是一种可变字长的编码,那什么是可变字长呢?就是一句话里的每一个字符(ASCII码)它的位数(长度)是不一样的.就像我们一句话(AAAACCCCCDDDDBBE)有A,B,C,D,E五种字符,在这里我们可以用01表示A字符,用001表示B字符,用11表示C字符,用10表示D字符,用000表示E字符.如下图: 既然知道了哈夫曼编码是什么了,那又有好奇的小朋友又会问了:那么哈夫曼编码是按照什么原理生成的呢? 在这里我就要告诉大家,哈夫曼编码是根据哈夫曼

《数据结构复习笔记》--哈夫曼树,哈夫曼编码

先来了解一下哈夫曼树. 带权路径长度(WPL):设二叉树有n个叶子结点,每个叶子结点带有权值 wk,从根结点到每个叶子结点的长度为 lk,则每个叶子结点的带权路径长度之和就是: 最优二叉树或哈夫曼树: WPL最小的二叉树. [例]有五个叶子结点,它们的权值为{1,2,3,4,5},用此权值序列可以构造出形状不同的多个二叉树. 其中结果wpl最小值的是:33=(1+2)*3+(3)*2+(4+5)*2: 哈夫曼树的构造: 每次把权值最小的两棵二叉树合并, 代码: typedef struct Tr

数据结构课程设计-哈夫曼编码译码

//******************************************** //程序功能:哈夫曼编码及译码 // //日期:2014年11月18 // //******************************************** #include<stdio.h> #include<stdlib.h> #include<string.h> #include <windows.h> #define MAX 128 //叶子节点

数据结构(java语言描述)哈夫曼编码

原理:哈夫曼编码是根据将已给出的权值作为叶子结点,生成一颗哈夫曼树,然后使得权重最小. 首先生成已给权重的所有的叶子结点,然后取所有节点中最小和次小的结点作为左右孩子生成一个哈夫曼树,计算出父节点的权重放入给出的权重森林中,并把之前的最小和次小的结点从森林中删除,再在种种森林中找最小和次小的结点生成权重树....直到最终只剩下一个树为止. 哈夫曼树的结点用如下结点表示: (有权重,左右孩子,父节点,然后设置一个标识符标志结点是否已经放入哈夫曼树) package tree;/**********

[数据结构] AVL树和AVL旋转、哈夫曼树和哈夫曼编码

1. AVL树 AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树.查找.插入和删除在平均和最坏情况下都是O(log n).增加和删除可能需要通过一次或多次树旋转来重新平衡这个树. 节点的平衡因子是它的左子树的高度减去它的右子树的高度(有时相反).带有平衡因子1.0或 -1的节点被认为是平衡的.带有平衡因子 -2或2的节点被认为是不平衡的,并需要重新平衡这个树.平衡因子可以直接存储在每个节点中,或从可能存储在节点中的子树高度计算出来. 1.2AVL旋转 AVL树的基本操作一

数据结构:哈夫曼编码(php版)

演示网址:http://huffman.sinaapp.com/ 源文件下载地址:http://xiaocao.u.qiniudn.com/work/huffman-2013-12-19.zip 概述下: 哈夫曼树─即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩. 在计算机信息处理中,"哈夫曼编码"是一种一致性编码法(又称"熵编码法"),用于数据的无损耗压缩.     简单的,就是靠权值排序,然后,转码,最优保存. 实现功能: 保存译码:在服务器端保存源