二叉搜索树
什么是二叉搜索树?
静态查找就是我们要找的元素是不动的。也就是说在一个集合上主要做的是find操作,而没有delete一个映射的这种操作发生。静态查找我们讲过的一个例子:二分查找就很nice
另外一种查找就是我们要找的这个对象的集合呢本身会动态的发生变化,也就是说经常要发生插入删除,除了查找之外还有插入删除操作发生。
二叉搜索树操作的特别函数:
二叉搜索树的查找操作:Find
对于尾递归这种操作的执行效率并不高,而且都可以使用循环的方式进行查询。
查找最大和最小元素:FindMin、FindMax
上面这种递归可以换成while循环的方式,效率更佳。
二叉搜索树的插入:Insert
二叉搜索树树的插入要保证插入之后的树仍然是二叉搜索树。
思路:
从根节点开始,如果根节点为空,那么说明这个树是空的,此时开辟一个空间,并赋值即可。
如果树不为空,那就通过递归的方式不断查找每一个节点,比节点数大的看其右子树,比节点数小的看其左子树,递归到最后一个节点后,其左右子树都为空,此时就通过开辟空间直接插入在这最后一个节点上,实现插入操作。
注意:上面的插入是按照字典顺序进行插入的,按照英文顺序排列的。A<B<C<D<E<F<G<……
说明:
一月 Jan. January
二月 Feb. February
三月 Mar. March
四月 Apr. April
五月 May. May
六月 Jun. June
七月 Jul. July
八月 Aug. August
九月 Sept. September
十月 Oct. October
十一月 Nov. November
十二月 Dec. December
二叉搜索树的删除:Delete
删除的如果是叶子节点,直接删除,将该叶子节点的父节点的左指针/或右指针设为NULL。
删除的如果是有一个孩子节点的节点,那么将父节点的指针不再指向这个要删除的节点,而是指向要删除的节点的孩子节点即可。
删除的如果是该节点有左右孩子,那么有两种删除方式:
1、取要删除的节点的右子树中最小的元素,并将该元素替换要删除的节点。
2、取要删除的节点的左子树中最大的元素,并将该元素替换要删除的节点。
习题练习:
讨论:搜索树比较序列的判别
代码:
代码:
BinTree Insert( BinTree BST, ElementType X )
{
if( !BST ){ /* 若原树为空,生成并返回一个结点的二叉搜索树 */
BST = (BinTree)malloc(sizeof(struct TNode));
BST->Data = X;
BST->Left = BST->Right = NULL;
}
else { /* 开始找要插入元素的位置 */
if( X < BST->Data )
BST->Left = Insert( BST->Left, X ); /*递归插入左子树*/
else if( X > BST->Data )
BST->Right = Insert( BST->Right, X ); /*递归插入右子树*/
/* else X已经存在,什么都不做 */
}
return BST;
}
BinTree Delete( BinTree BST, ElementType X )
{
Position Tmp;
if( !BST )
printf("要删除的元素未找到");
else {
if( X < BST->Data )
BST->Left = Delete( BST->Left, X ); /* 从左子树递归删除 */
else if( X > BST->Data )
BST->Right = Delete( BST->Right, X ); /* 从右子树递归删除 */
else { /* BST就是要删除的结点 */
/* 如果被删除结点有左右两个子结点 */
if( BST->Left && BST->Right ) {
/* 从右子树中找最小的元素填充删除结点 */
Tmp = FindMin( BST->Right );
BST->Data = Tmp->Data;
/* 从右子树中删除最小元素 */
BST->Right = Delete( BST->Right, BST->Data );
}
else { /* 被删除结点有一个或无子结点 */
Tmp = BST;
if( !BST->Left ) /* 只有右孩子或无子结点 */
BST = BST->Right;
else /* 只有左孩子 */
BST = BST->Left;
free( Tmp );
}
}
}
return BST;
}