Binary Search Tree(Ordered Binary Tree) - 二叉查找树(有序二叉树)


遍历

二叉查找树和二分查找算法的思路一样,但使用树形结构来实现。

BinarySearchTree1.png

二叉查找树上节点的左孩子节点为,右孩子节点为。二叉查找树上任意节点的左子树上所有节点都小于,右子树上所有节点都大于,即。二叉查找树中不允许两个相等的节点(通过一些方法可以实现包含重复键值的二叉查找树,但为了方便本文中不考虑这种情况)。

拥有个节点且安排良好的(金字塔型的)二叉查找树可以在的时间复杂度内查找任意元素。在二叉查找树上查询一个节点的过程和二分查找完全一样,从根节点开始依次比较被查找的节点和当前节点,若则查找结束;若则继续在左子树中查找;若则继续在右子树中查找:

BinarySearchTree2.png

二叉树有四种遍历方式:

先序遍历(),访问顺序总是

后序遍历(),访问顺序总是

中序遍历(),访问顺序总是

层序遍历(),访问顺序类似BFS算法,一层一层的访问所有节点);

下图中节点的访问顺序按照数字从小到大:

BinarySearchTree6.png

BinarySearchTree7.png

插入

往二叉查找树插入节点时,首先在树上尝试搜索,搜索失败时会停下的节点就是合适插入的位置。若则将其作为的左孩子节点,若则将其作为的右孩子节点。为了方便我们不考虑重复插入的情况。

BinarySearchTree3.png

删除

从二叉查找树中删除节点时需要保证二叉查找树的属性(),有三种情况:

为叶子节点,既没有左孩子节点也没有右孩子节点,直接删除;

只有一个孩子节点,则像链表一样将从其父节点和之间删除;

同时有左右孩子节点,按照中序遍历找出二叉树中比大的下一个节点(中序遍历下的后继节点),用其值代替,再继续用相同的规则递归的删除原始节点(实际上,中序遍历的后继节点不可能存在左孩子节点,要么无孩子节点,要么只有右孩子节点);

下图演示了上述的三种删除情况,其中红色节点是待删除节点:

BinarySearchTree8.png

BinarySearchTree9.png

BinarySearchTree10.png

BinarySearchTree11.png

待删除节点没有左右孩子节点,直接删除即可;

待删除节点只有右孩子节点,用代替即可;

待删除节点拥有左右孩子节点,用的中序遍历的下一个节点代替它,然后用相同的规则递归删除原始的节点(在这种情况下,节点没有左右孩子节点,因此直接删除);

待删除节点拥有左右孩子节点,用的中序遍历的下一个节点代替它,然后用相同的规则递归删除原始的节点(在这种情况下,节点只有右孩子节点,因此用替换即可);

随机的插入/删除会让二叉查找树退化为链表,如图所示是一个糟糕的二叉查找树,虽然它满足节点之间有序,但是查找的时间复杂度已经退化为了

BinarySearchTree5.png


源码

BinarySearchTree.h

BinarySearchTree.cpp

测试

BinarySearchTreeTest.cpp