哈夫曼编码树、优先队列、二叉检索树

目录

哈夫曼编码树
                 基本定义
                 代码分析 
                 分析总结 

 二叉检索树
                 定义
                 代码实现
                ​​​ 二叉树的平衡 
优先队列
                概述
                实现


本文需要对树结构有个基础的认识,如有需要可以看

树的相关知识_--舞动程序-优快云博客

哈夫曼编码树

引用:3.3哈夫曼编码树 (xjtuse-guide.github.io)

基本定义

路径长度:两个结点之间路径上的分支数

树的外部路径长度:各叶结点到根结点的路径长度之和

树的内部路径长度:各非叶结点到根结点的路径长度之和

树的带权路径长度:树中所有叶子结点的带权路径长度之和


说的通俗一些,就是我们对树中的元素访问的频率不同,比如字母a用的多,v用的少,这个使用频率就是一个权值,访问频率大的元素,我们更想把它放在“浅”的地方,而很少访问的元素,我们就可以把它放在“深”一点的地方,也就是路径长度大的地方,用加权计算可以得到左后的带权路径长度。

而我们的哈夫曼编码树就是希望通过计算机生成一个最优排布,让树的带权路径长度最短,相对来说访问效率也就最快


 代码分析 

eg.访问速度的缩短比较显然,下面的例子体现哈夫曼树的其他优势


利用Huffman树的特性为使用频率不同的字符编写不等长的编码,从而缩短整个文件的长度

This is isinglass

■ t的频度是1             h的频度是1                    i的频度是4           a的频度是1

s的频度是5               n的频度是1                    g的频度是1           I的频度是1

如果采用等长的编码形式,上面的八个字母则需要三位二进制编码 长度=15*3=45

按照上面字母出现的频度创建一个Huffman树


 我们需要完成两件事,第一是定义二叉树的节点信息(包含权值),第二则是构建哈夫曼树

构建节点数据类型,letter和HuffTreeNode类放一起,难度相对不高

class Letter {
    char element;//字母
    double weight;//字母出现的频率

    public Letter(char element, double weight) {
        this.element = element;
        this.weight = weight;
    }
    //get和set一类的省略了
}
class HuffTreeNode {
    Letter letter;
    HuffTreeNode left;//左子结点
    HuffTreeNode right;//右子结点

    public Letter getLetter() { return letter;}

    public void setLetter(Letter letter) {    this.letter = letter;  }

    public HuffTreeNode getLeft() { return left;  }

    public void setLeft(HuffTreeNode left) {this.left = left; }

    public HuffTreeNode getRight() { return right; }

    public void setRight(HuffTreeNode right) {this.right = right;}
}

下面是哈夫曼树的生成过程,用文字描述就是

1.将两个访问频率最小的节点(x,y)挂在一个新节点z下,z的访问频率等于二者之和

2.将z加入排序中,和其他的节点放在一起(剔除x,y),重复1,2过程

3.当结点序列中只剩下一个结点,它的访问频率是100%,这就是树的root。

每次选两个最小的捏成一个 =>捏的只剩一个图解来源于:3.3哈夫曼编码树 (xjtuse-guide.github.io)icon-default.png?t=N7T8https://xjtuse-guide.github.io/Xjtuse-Guide/#/docs/%E8%AF%BE%E5%86%85%E7%AC%94%E8%AE%B0/%E5%A4%A7%E4%BA%8C%E4%B8%8A/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95/%E7%AC%94%E8%AE%B0/%E6%98%93%E4%BF%8A%E6%B3%89/3.3%E5%93%88%E5%A4%AB%E6%9B%BC%E7%BC%96%E7%A0%81%E6%A0%91?id=%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5


public class HuffmanTree {
    //简单使用冒泡排序
    private void sort(HuffTreeNode[] nodes) {
        int flags = 0;
        for (int i = 0; i < nodes.length-1; i++) {
            for (int j = 0; j < nodes.length-1-i; j++) {
                if (nodes[j].letter.weight > nodes[j + 1].letter.weight) {
                    HuffTreeNode temp = nodes[j];
                    nodes[j] = nodes[j + 1];
                    nodes[j + 1] = temp;
                    flags = 1;//不是有序的,flags设置为1;

                }
            }
            if (flags == 0)
                return;
        }
    }

 
    public HuffTreeNode generateHuffTree(Letter[] letters) {
        HuffTreeNode[] nodes = new HuffTreeNode[letters.length];
        for (int i = 0; i < letters.length; i++) {
            nodes[i] = new HuffTreeNode();
            nodes[i].letter = letters[i];
        }//初始化数组
        while (nodes.length > 1) {
            sort(nodes);
            HuffTreeNode node1 = nodes[0];
            HuffTreeNode node2 = nodes[1];
            HuffTreeNode newTree = new HuffTreeNode();
            Letter temp = new Letter('0',node1.getLetter().getWeight()+node2.getLetter().getWeight());
            newTree.setLetter(temp);
            newTree.setLeft(node1);
            newTree.setRight(node2);
            //完成一次子树生成
            HuffTreeNode[] nodes2 = new HuffTreeNode[nodes.length - 1];//新的结点数组,长度减一
            for (int i = 2; i < nodes.length; i++) {
                nodes2[i - 2] = nodes[i];
            }
            nodes2[nodes2.length - 1] = newTree;
           //新的结点数组初始化完成
            nodes = nodes2;
        }
        return nodes[0];
    }
//下面还有部分

截止到这里,我们已经完成了对哈夫曼树的构建和生成,下面将用一种输出方法将结果更好的表现出来,而这种输出方法也更好的说明了哈夫曼树体现出优势的核心原因

 public void print(HuffTreeNode root,String code){
        if(root != null) {
            print(root.getLeft(),code+"0");
            print(root.getRight(),code+"1");
            if(root.getLeft() == null && root.getRight() == null) {
                String m=root.getLetter().getElement()+"频数:"+root.getLetter().getWeight()+" 哈夫曼编码:"+code;
                System.out.println(m);
            }
        }
    }
    public static void main(String[] args) {
        Letter a = new Letter('a', 1);
        Letter g = new Letter('g', 1);
        Letter h = new Letter('h', 1);
        Letter l = new Letter('l', 1);
        Letter n = new Letter('n', 1);
        Letter t = new Letter('t', 1);
        
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值