数据结构:真不难,记一次字节跳动Java社招面试

  1. 深度为k的二叉树最多有2k-1个节点

  2. 对于任意二叉树,终端结点数(叶子结点数)为 n0,度为 2 的结点数为 n2,则 n0=n2+1,

    即度为0的节点n0,永远比度为2的节点 n2多一个。

    若排版问题可看图

满二叉树


二叉树中除了叶子节点,每个节点的度都为2,则此二叉树为满二叉树。

具有 n 个节点的满二叉树的深度为: log2(n+1)

image-20210714002538228

完全二叉树


一棵二叉树中,只有最下面两层结点的度可以小于2,并且最下一层的叶结点集中在靠左的若干位置上。这样的二叉树称为完全二叉树。叶子结点只能出现在最下层和次下层,且最下层的叶子结点集中在树的左部。显然,一棵满二叉树必定是一棵完全二叉树,而完全二叉树未必是满二叉树。

image-20210714003735456

哈夫曼树(最优二叉树)


若给定一个二叉树如下:

image-20210714135953216

路径:在一棵树中,一个节点到另一个节点之间的通路,称为路径。如上图中的根节点到a之间的通路。

路径长度:在一条路径中,每经过一个节点,路径长度就加1。如上图根节点到节点c的路径长度为3。

节点的权:每个节点赋予一个新的数值。如a的权为7,b的权为5。

节点的带权路劲长度:从根结点到该结点之间的路径长度与该结点的权乘积。如b的带权路径长度为2*5=10。

树的带权路径长度:树中所有叶子结点的带权路径长度之和。通常记作 “WPL” 。如图中所示的这颗树的带权路径长度为:WPL = 7 * 1 + 5 * 2 + 2 * 3 + 4 * 3

什么是哈夫曼树

构造一棵二叉树(每个节点都是叶子结点且都有各自的权值),该树的带权路径长度达到最小,称为最优二叉树,也称为哈夫曼树(Huffman Tree)

编码问题

场景:给定一段字符串,包含58个字符,且由以下7个字符构成:a,b,c,d,e,f,g,这7个字符出现的频次不同,如何对这7个字符进行编码如何对字符串进行编码,可以使得该字符串的编码存储空间最少?

image-20210714141834626

如果用标准的等长ASCII编码:58 × 8 = 464位

用二叉树进行编码

若用0和1表示左右分支,取出上面4个频次最高的字符,可以得到如下一棵树:

image-20210714143322940

image-20210714150513498

由上图可知,编码为0100可表示的字符就有3种可能的情况,因此,上面节点的分布具有二义性。如何避免二义性?只需要让每个节点都是叶子节点即可。

image-20210714152035199

哈夫曼树图示构造

通过上面的方式,我们把上面的字符按频次依次两两组合,且都为叶子节点。最后构造图示如下:

image-20210714230327864

因此,我们发现每个节点都是叶子节点,字符最后的编码为:

image-20210714230617039

所以,编码长度为:

10x3 + 15x2 + 12x2 + 3x5 + 4x4 + 13x2 + 1x5 = 146位

代码构造


public class HuffmanTree {



    //节点

    public static class Node<E> {

        //数据,如a,b,c,d。。。

        E data;

        //权重

        int weight;

        //左子节点

        Node leftChild;

        //you子节点

        Node rightChild;



        public Node(E data, int weight) {

            this.data = data;

            this.weight = weight;

        }

		

        public String toString() {

            return "Node[" + weight + ",data=" + data + "]";

        }

    }



    public static Node createHuffmanTree(List<Node> nodeList) {

        //当节点大于1时

        while (nodeList.size() > 1) {

            //先对list中根据权重排序

            sort(nodeList);

            //排序之后第一个节点就是权重最小的节点,第二个节点就是权重第二小的节点

            Node left = nodeList.get(0);

            Node right = nodeList.get(1);

            //生成一个新的父节点,类似于步骤1,但父节点没有数据只有权值

            Node<Node> parent = new Node<>(null, left.weight + right.weight);

            //子节点和父节点链接

            parent.leftChild = left;

            parent.rightChild = right;

            //删除最小的节点

            nodeList.remove(0);

            //删除第二小的

            nodeList.remove(0);

            //添加到list中

            nodeList.add(parent);

        }

        //最后返回根节点一棵树

        return nodeList.get(0);

    }



    /**

     * 冒牌排序

     *

     * @param nodeList

     */

    public static void sort(List<Node> nodeList) {

        if (nodeList.size() <= 1) {

            return;

        }

        for (int i = 0; i < nodeList.size(); i++) {

            for (int j = 0; j < nodeList.size() - 1; j++) {

                //前面的数大于后面的数就交换

                if (nodeList.get(j + 1).weight < nodeList.get(j).weight) {

                    Node temp = nodeList.get(j + 1);

                    nodeList.set(j + 1, nodeList.get(j));

                    nodeList.set(j, temp);

                }

            }

        }

    }



    /**

     * 打印哈夫曼树,先左后右


## 结语

小编也是很有感触,如果一直都是在中小公司,没有接触过大型的互联网架构设计的话,只靠自己看书去提升可能一辈子都很难达到高级架构师的技术和认知高度。向厉害的人去学习是最有效减少时间摸索、精力浪费的方式。

我们选择的这个行业就一直要持续的学习,又很吃青春饭。

虽然大家可能经常见到说程序员年薪几十万,但这样的人毕竟不是大部份,要么是有名校光环,要么是在阿里华为这样的大企业。年龄一大,更有可能被裁。

小编整理的学习资料分享一波!

送给每一位想学习Java小伙伴,用来提升自己。**[想要资料的可以点击这里免费获取](https://gitee.com/vip204888/java-p7)**
![在这里插入图片描述](https://img-blog.csdnimg.cn/img_convert/ac4ca613fb2ff57bc54f486886349feb.png)

达到高级架构师的技术和认知高度。向厉害的人去学习是最有效减少时间摸索、精力浪费的方式。

我们选择的这个行业就一直要持续的学习,又很吃青春饭。

虽然大家可能经常见到说程序员年薪几十万,但这样的人毕竟不是大部份,要么是有名校光环,要么是在阿里华为这样的大企业。年龄一大,更有可能被裁。

小编整理的学习资料分享一波!

送给每一位想学习Java小伙伴,用来提升自己。**[想要资料的可以点击这里免费获取](https://gitee.com/vip204888/java-p7)**
[外链图片转存中...(img-glYOReK8-1628626892122)]

> 本文到这里就结束了,喜欢的朋友可以帮忙点赞和评论一下,感谢支持!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值