二叉查找树(BST)也称为二叉搜索树或二叉排序树,二叉查找树的节点包含键值key。它的左子树不为空,那么左子树上所有节点的key都小于根节点的key
它的右子树不为空,那么右子树上所有节点的key都大于根节点的key
它的左右子树也分为二叉排序树。
遍历分为:
前序遍历(DLR):树根->左子树->右子树
先访问根节点,在遍历左子树,最后遍历右子树。并且在遍历左右子树时,仍需先访问根节点,然后遍历左子树,最后遍历右子树。如图遍历顺序为ABDGHCEIF
![6c9c1ef6c364b292354a43f397bf3448.png](https://i-blog.csdnimg.cn/blog_migrate/1cd5d84c5425b894a2dbe9f9d9d8aff8.jpeg)
代码如下:
public void preOrder(Node root){
if(root != null){
syso(root.getValue() + “ ”);
//递归调用
preOrder(root.leftChild);
preOrder(root.rightChild);
}
}
中序遍历(LDR):左子树->树根->右子树
先遍历左子树,然后访问根节点,最后遍历右子树;并且在遍历左右子树的时候,仍然先遍历左子树,然后访问根节点,最后遍历右子树
如图遍历节点顺序为:GDHBAEICF
![c26aa9d9ba35ae26af199470895d5667.png](https://i-blog.csdnimg.cn/blog_migrate/f305a0a312c0df98f585ac0dd5725355.jpeg)
public void inOrder(Node root){
if(root != null){
inOrder(root.leftChild);
syso(root.getValue() + “ ”);
inOrder(root.rightChild);
}
}
后序遍历(LRD):左子树->右子树->树根
先遍历左子树,然后遍历右子树,最后访问根节点;先遍历左子树,然后遍历右子树,最后访问根节点。如图节点遍历顺序为GHDBIEFCA
![cc3c19942027f9fb0a8b9eb0b8ac841f.png](https://i-blog.csdnimg.cn/blog_migrate/c5ba52f52a3dd7af63a6e8020f162240.jpeg)
public void postOrder(Node root){
if(root != null){
postOrder(root.leftChild);
postOrder(root.rightChild);
syso(root.getValue() + “ ”);
}
}
二叉排序树的查找:
先比较根节点的值,如果要查找的值小于根节点,则查找根节点的左孩子节点,然后继续与对比,如果大于节点值,则查找右孩子节点,依次类推,直到查找到并返回结果或者没有查找到返回提示。
二叉排序树的插入:与查找类似,只不过一直找到叶子结点,若没有重复,则将待插入节点作为新的叶子结点插入。
二叉排序树的删除:
- 首先遍历二叉排序树,如果不存在要删除的节点,则不做任何操作
- 否则分三种情况讨论:
- 待删节点是叶子结点,则直接删除
- 待删节点只有左子树或者只有右子树,则将待删节点的父节点的引用置位该节点的孩子节点
待删节点既有左子树又有右子树,可以使用左子树的最大节点(直接前驱节点)或右子树的最小节点(直接后继节点)。
二叉树与快速排序的结合:
这两天一直在思考树形结构与快速排序的结合优化。因为两者都具备“递归”和“二分”的思想,只不过数据结构不同。并且很明显在多数情况下,使用树形结构排序,时间复杂度要比数组更低一些。树形结构进行排序时,只需要先将数组元素插入树中,然后按照中序遍历的方法,取出来存放到数组中,那么就完成了数组的排序。
当给出一组数列时,我们可以将数列中的元素,迁移到树形结构(Tree)中,为了避免将逆序列排成正序列或者将正序列排列成逆序列的情况出现,我们这里可以先将第一个数(left),最后一个数(right),中间一个数(mid)取出来,取出这三个数的中间数,来作为树的根节点。然后遍历数组,依次从数组中取出每一个元素,与根节点对比,如果比根节点大,则放在右孩子节点,反之放在左孩子节点。然后接着取出下一个数组元素,从根节点开始进行比较,然后跟根节点的子孩子节点比较,直到最后,然后插入树结构中。
如果我们采用平衡二叉树(Self-balancing binary search tree)的树形结构,平衡二叉树能保证数据的左右两边的节点层级相差不会大于1.,通过这样避免树形结构由于删除增加变成线性链表影响查询效率,保证数据平衡的情况下查找数据的速度近于二分法查找;当在这里这样做就将数组中的元素分为了两部分,在插入完成后,按照中序遍历即可。但是使用平衡二叉树,可能会造成节点的频繁移动,影响算法的时间复杂度,但是结果又很美观,并且方便遍历。
在树形结构中运用递归不断的对比,每次对比之后中,都会将查找范围缩小一半,这里相当于快速排序的一种优化。