二叉排序树:
二叉排序树,又称为二叉查找树。它或者是一棵空树,或者是具有下列性质的二叉树。
1.若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
2.若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
3.它的左、右子树也分别为二叉排序树。
构造一颗二叉排序树的目的,其实并不是为了排序,而是为了提高查找和插入删除关键字的速度。
在一个有序数据集上的查找,速度总是要快于无序的数据集的,而二叉排序树这种非线性的结构,也有利于插入和删除的实现。
查找算法:
结点类:可以自行修改为泛型,参考前面的排序算法泛型的修改。
public class BitNode
{
public int data;
public BitNode leftChild;
public BitNode rightChild;
}
/// <summary>
/// 递归查找二叉排序树tree中是否存在key
/// </summary>
/// <param name="tree">二叉树根结点</param>
/// <param name="key">查找的关键字</param>
/// <param name="parent">指向tree的双亲,初始值为null</param>
/// <param name="result">查找成功:result指向对应key的结点
/// 查找失败:指向查找路径上访问的最后一个结点</param>
/// <returns></returns>
public bool SearchBST(BitNode tree, int key, BitNode parent, BitNode result)
{
if (tree == null) //查找不成功
{
result = parent;
return false;
}
else if (key == tree.data) //查找成功
{
result = tree;
return true;
}
else if (key < tree.data)
{
return SearchBST(tree.leftChild, key, parent, result);
}
else
{
return SearchBST(tree.rightChild, key, parent, result);
}
}
插入算法:可以用于新建二叉排序树
/// <summary>
/// 二叉排序树的插入:也可以用来新创建一颗二叉排序树
/// </summary>
/// <param name="tree">根结点</param>
/// <param name="key">插入的key值</param>
/// <returns></returns>
public bool InsertBST(BitNode tree, int key)
{
BitNode p = null;
BitNode insertNode = null;
if (!SearchBST(tree, key, null, p)) //查找不成功
{
insertNode = new BitNode();
insertNode.data = key;
insertNode.leftChild = insertNode.rightChild = null;
if (p == null)
{
tree = insertNode; //插入s为新的根结点
}
else if (key < p.data)
{
p.leftChild = insertNode; //插入s为左孩子
}
else
{
p.rightChild = insertNode; //插入s为右孩子
}
return true;
}
else
{
return false; //树中已有关键字相同的结点,不再插入
}
}
删除二叉排序树上的结点:推荐看书上的详细过程
/// <summary>
/// 删除二叉排序树上结点
/// </summary>
/// <param name="tree"></param>
/// <param name="key"></param>
/// <returns></returns>
public bool DeleteBST(BitNode tree, int key)
{
if (tree == null)
{
return false;
}
else
{
if (key == tree.data)
{
return Delete(tree);
}
else if (key < tree.data)
{
return DeleteBST(tree.leftChild, key);
}
else
{
return DeleteBST(tree.rightChild, key);
}
}
}
private bool Delete(BitNode node)
{
BitNode p = null;
BitNode s = null;
if (node.rightChild == null) //右子树空则只需重接它的左子树
{
node = node.leftChild;
}
else if (node.leftChild == null) //左子树空则只需重接它的右子树
{
node = node.rightChild;
}
else //左右子树均不空
{
p = node;
s = node.leftChild;
while (s.rightChild != null)
{
p = s;
s = s.rightChild;
}
node.data = s.data; //s指向被删结点的直接前驱
if (p != node)
{
p.rightChild = s.leftChild; //重接q的右子树
}
else
{
p.leftChild = s.leftChild; //重接q的左子树
}
}
return true;
}
二叉排序树的查找性能取决于二叉排序树的形状,问题在于二叉排序树的形状是不确定的。