算法筑基(七)树

149 阅读4分钟

看图说话

image.png

image.png 和大自然中的树是一样的,只不过倒过来了。

名词解释:

  • 是一种数据结构,它是由n(n≥0)个有限节点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点:

  • 每个节点有零个或多个子节点;没有父节点的节点称为根节点;一棵树当中没有子结点的结点称为叶子结点,每一个非根节点有且只有一个父节点;除了根节点外,每个子节点可以分为多个不相交的子树。

这些名词只要联想类比大自然的树就很清晰明了。

  • 如果子树相交,那它就变成了

  • 如果每个节点的只有一个子节点那它就变成了单链表

  • 树形结构特别有意思的是,它就好比我们人生的各种选择,不同的选择走向不同的结果。

二叉树

定义:二叉树(binary tree)是指树中节点的度不大于2有序树,它是一种最简单且最重要的树。

public class TreeNode{
    public int val;
    public TreeNode left, right;
    public TreeNode(int val){ 
        this.val = val; this.left = null; this.right = null; 
    } 
}

二叉树的遍历

分为前序,中序,后序遍历。以这个树形结构为例

2.PNG

前序遍历 :先访问根节点,再访问左节点,再访问右节点。

所以输出顺序为:A,B,D,E,H,C,F,I,G

image.png

中序遍历:先访问左节点,再访问根节点,再访问右节点。

所以输出顺序为:D,B,H,E,A,F,I,C,G

image.png

后序遍历:先访问左节点,再访问右节点,再访问根节点。

所以输出顺序为:D,H,E,B,I,F,G,C,A

image.png

是不是看着递归的写法很简单,前序就将System.out.println()放前面,中序就放中间,后序就放后面。这是因为虚拟机在执行代码的时候隐式维护了一个调用栈。那要让我们自己实现一个迭代算法怎么实现呢。大家可以通过真题去练习一下:

除了这三种遍历还有一种层序遍历,就是按照从上到下的层级顺序,一层一层输出。还用上面的这个结构为例,

2.PNG

它的层序遍历的结果 : A,B,C,D,E,F,G,H,I

3.PNG

我们发现层序遍历使用的是Queue这个数据结构。而之前的前序中序后序遍历使用的使Stack,这就使BFS和DFS典型的实现上的区别。BFS(Breadth First Search),DFS(Depth First Search)不在本章讨论范围内,后续再介绍。

二叉搜索树(Binary Search Tree)

image.png

又称:二叉搜索树,二叉排序树)

条件

  • 左子树小于根节点

  • 右子树大于根节点

  • 左右子树也满足这一条件

  • 中序遍历是升序遍历

特点:

它既有链表的快速插入与删除操作的特点,又有数组快速查找的优势;,所以应用十分广泛,例如在文件系统和数据库系统一般会采用这种数据结构进行高效率的排序与检索操作。

通过前面的了解,看看能否做出这个题:

判断是否是二叉搜索树

平衡二叉树(AVL)

Wiki:在计算机科学中,AVL树是最早被发明的自平衡二叉查找树。在AVL树中,任一节点对应的两棵子树的最大高度差为1,因此它也被称为高度平衡树。查找、插入和删除在平均和最坏情况下的时间复杂度都是O(logn)

重点:任一节点对应两颗子树的最大高度差为1.

image.png

为什么有了二叉搜索树,又来了个平衡二叉树?

原因是:二叉搜索树一定程度上可以提高搜索效率,但是当原序列有序时,例如序列 A = {A,B,C,D,E,F},构造二叉搜索树。依据此序列构造的二叉搜索树为右斜树,同时二叉树退化成单链表,搜索效率降低为 O(n)。

4.PNG

平衡二叉树又是如何解决这个问题的?

二叉搜索树的查找效率取决于树的高度,因此保持树的高度最小,即可保证树的查找效率。同样的序列 A,将其改为平衡二叉树的方式存储,查找元素 6 时只需比较 3 次,查找效率提升一倍。

二叉树又是如何保持平衡的呢

当树出现不平衡的时候进行平衡调整。怎么平衡调整(未完待续)

参考链接:zhuanlan.zhihu.com/p/56066942

红黑树

一种近似平衡二叉树,注意是近似平衡,既然是近似平衡,所以它对左右子树高度差的要求是,任何一个左右子树的高度差小于两倍,

为什么有了平衡二叉树,又来了个红黑树呢

因为高度差不用那么严格,所以调整次数少,进而提高了插入和删除的效率