顾名思义,二叉搜索树是以一棵二叉树来组织的,这样的一棵树可以用一个链表结构来表示,每个节点除了data还有left、right、parent,分别指向节点的左孩子,右孩子和父节点。如果对应的节点不存在则指向NIL节点。(因为最简单的二叉搜索树中的NIL节点里并没有有用信息,所以在实现时简单的指向NULL也是可以的,本文中就会这么实现)
二叉搜索树的性质
- 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
- 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
- 它的左右子树也分别是二叉搜索树
二叉树的常用操作
二叉树的查找
若根节点不为空,则:
- 如果要查找的值与根节点的值相同,即要查找data==根节点data,则返回true;
- 如果要查找的值比根节点的值小,即要查找data<根节点data,则在其左子树进行查找
- 如果要查找的值比根节点的值大,即要查找data>根节点data,则在其右子树进行查找
二叉树的插入
树为空,则直接进行插入
树不空,按二叉搜索树性质查找插入位置,插入新节点
1.按照二叉树的性质,先找到插入节点的位置
root->5,5<10,root = root->right,parent = root;
root->7,7<10,root = root->right,parent = root;
root->8,8<10,root = root->right,parent = root;
root->9,9<10,root = root->right,parnet = root;
2.插入新节点
二叉树的删除
首先查找元素是否在二叉搜索树中,如果不存在,则返回, 否则要删除的结点可能分下面四种情况:
1
2
3
4a. 要删除的结点无孩子结点
b. 要删除的结点只有左孩子结点
c. 要删除的结点只有右孩子结点
d. 要删除的结点有左、右孩子结点看起来有待删除节点有4中情况,实际情况a可以与情况b或者c合并起来,因此真正的删除过程如下:
情况b:删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点
情况c:删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点
情况d:在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点中,
再来处理该结点的删除操作
二叉树的实现
1 | #pragma once |
二叉树的性能分析
插入和删除操作都必须先查找,查找效率代表了二叉搜索树中各个操作的性能。
对于有n个结点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二叉搜索树的深度的函数,即结点越深,则比较次数越多。
但对于同一个关键码集合,如果各关键码插入的次序不同,可能得到不同结构的二叉搜索树:
也就是说:
最优情况下,二叉搜索树为完全二叉树,其平均比较次数为:
最差情况下,二叉搜索树退化为单支树,其平均比较次数为: