一.定义
数据集无序方便插入与删除 有序利于查找
在一般情况下,查询效率比链表结构要高
二.性质
1.若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
2.若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
3。左、右子树也分别为二叉排序树(递归)
4.没有键值相等的结点
三.查找操作
遍历采用中序遍历,这样成为了有序
1.二叉树的结构
2.代码
四.插入操作
插入要先查找是否存在 存在则不再插入 插入就是将关键字放到树中合适的位置
五.删除操作
删除的核心思想就是 不是特殊结点(既有左孩子又有右孩子 处于中间位置)只需要释放结点 把剩下部分连在一起即可
对于特殊结点(例如上图105) 则需要用**它的前驱或者是后驱 把它的数据给替换掉 释放其前驱或者后驱 再连接其余结点
//删除操作
Status DeleteBST(BiTree *T, int key)
{
if(!*T)
{
return FALSE;
}
else
{
if(key == (*T) -> data)
{
return Delete(T);
}
else if(key < (*T) -> data)
{
return DeleteBST(&(*T) -> lchild, key);
}
else
{
return DeleteBST(&(*T) -> rchild, key);
}
}
}
Status Delete(BiTree *p)
{
BiTree q, s;
if((*p) -> rchild == NULL) //右子树为空只需要重接它的左子树
{
q = *p;
*p = (*p) -> lchild;
free(q);
}
else if((*p) -> lchild == NULL) //只需重接它的右子树
{
q = *p;
*p = (*p) -> rchild;
free(q);
}
else //利用前驱 把前驱的数据和要删除的结点数据交换 释放掉前驱
{
q = *p;
s = (*p) -> lchild;
while(s -> rchild) //一直找到最右的 即前驱
{
q = s;
s = s -> rchild; //s是前序结点 q是s的双亲结点
}
(*p) -> data = s -> data;
if(q != *p)
{
q -> lchild = s -> lchild;
}
else
{
q -> lchild = s -> lchild;
}
free(s);
}
return TRUE;
}
六.总结
二叉排序树的查找性能取决于二叉排序树的形状
我们希望二叉排序树是比较平衡的 即其深度与完全二叉树相同 进而引出平衡二叉树的问题