4.1二叉搜索树

二叉搜索树

查找问题

  • 静态查找和动态查找
  • 针对动态查找,数据如何组织?

二叉搜索树的性质

  1. 非空左子树的所有键值小于其根结点的键值。
  2. 非空右子树的所有键值大于其根结点的键值。
  3. 左、右子树都是二叉搜索树。

二叉搜索树的特别函数

  • Position Find( ElementType X, BinTree BST )
  • Position FindMin( BinTree BST )
  • Position FindMax( BinTree BST )
  • BinTree Insert( ElementType X, BinTree BST )
  • BinTree Delete( ElementType X, BinTree BST )
二叉搜索树的查找操作Find
Position Find( ElementType X, BinTree Bst )
{
    if( !BST ) return NULL; // 查找失败
    if( X > BST->Data )
        return Find( X, BST->Right );//在右子树中继续查找
    else if( x < BST->Data )
        return Find( X, BST->Left );//在左子树中继续查找
    else // X == BST->Data
        return BST; // 查找成功,返回结点的找到结点的地址
}  // 尾递归可以用循环代替
  • 由于非递归函数的执行效率高,可将“尾递归”函数改为迭代函数
Position IterFind( ElementType X, BinTree BST )
{
    while( BST ) {
        if( X > BST->Data )
            BST = BST->Right; // 向右子树中移动,继续查找
        else if( X < BST->Data ) 
            BST = BST->Left;
        else // X == BST->Data
            return BST; // 查找成功,返回结点的找到结点的地址
    }
    return NULL; // 查找失败
}
  • 查找的效率决定于树的高度
查找最大和最小元素
  • 最大元素一定是在树的最右分枝的端结点上
  • 最小结点一定在最左分枝的端结点上

查找最小元素的递归函数

Position FindMin( BinTree BST )
{
    if( !BST) return NULL; // 空的二叉搜索树,返回NULL
    else if( !BST->Left )
        return BST; // 找到最左叶结点并返回
    else 
        return FindMin( BST->Left); // 沿左分枝极限查找
}

查找最大元素的迭代函数

Position FindMax( BinTree BST )
{
    if( BST )
        while( BST->Right ) BST = BST->Right;
    		//沿右分支继续查找,直到最右叶结点
    return BST;
}
二叉搜索树的插入
  • 分析:关键是要找到元素应该插入的位置,可以采用与Find类似的方法
BinTree Insert( ElementType X, BinTree BST )
{
    if( !BST ) {
        	// 若原树为空,生成并返回一个结点的二叉搜索树
        BST = malloc(sizeof(struct TreeNode));
        BST->Data =X;
        BST->Left = BST->Right = NULL;
    } else // 开始找要插入元素的位置
        if( X < BST->Data )
            BST->Left = Insert( X, BST->Left);
    			// 递归插入左子树
    	else if( X > BST->Data )
            BST->Right = Insert( X, BST->Right);
    		// else X已经存在,什么都不做
   return BST;
}
二叉搜索树的删除
  • 考虑三种情况:

    1. 要删除的是叶结点:

      直接删除,并改变其父结点指针–置为NULL

    2. 要删除的结点只有一个孩子结点:

      将其父结点的指针指向要删除结点的孩子指针

    3. 要删除的结点有左、右两颗子树:

      用另一结点代替被删除结点:右子树的最小元素 或 左子树的最大元素

BinTree Delete( ElementType X, BinTree BST )
{
    Position Tmp;
    if( !BST ) printf("要删除的元素未找到");
    else if( X < BST->Data )
        BST->Left = Delete( X, BST->Left);//左子树递归删除
    else if( X > BST->Data )
        BST->Right = Delete( X, BST->Right);
    else // 找到要删除的结点
        if( BST->Left && BST->Right ) {//被删除结点有左右两个结点
            Tmp = FindMin( BST->Right );
            	//在右子树中找到最小的元素填充删除结点
            BST->Data = Tmp->Data;
            BST->Right = Delete( BST->Data, BST->Right);
           // 在被删除结点的右子树中删除最小元素
        } else { // 被删除结点有一个或无结点
            Tmp = BST;
            if( !BST->Left ) // 有右孩子或无结点
                BST = BST->Right;
            else if( !BST->Right )
                BST = BST->Left;
            free( Tmp );
        }
    retutn ( Tmp );
}
 BST = BST->Right;
            else if( !BST->Right )
                BST = BST->Left;
            free( Tmp );
        }
    retutn ( Tmp );
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值