二叉搜索树(C语言)

二叉搜索树

什么是二叉搜索树

二叉搜索树(BST,Binary Search Tree),也称二叉排序树二叉查找树

二叉搜索树:一棵二叉树,可以为空;如果不为空,满足以下性质:

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

二叉搜索树例子:
二叉搜索树例子
二叉搜索树例子2

二叉搜索树的一些操作

  1. Position Find(ElementType X,BinTree BST):从二叉搜索树BST中查找元素X,返回其所在结点的地址;

    • 递归实现

      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
          {
              return BST;
          }
      }
      
    • 非递归实现:由于非递归函数的执行效率高,可将“尾递归”函数改为迭代函数。

      Position Find(ElementType X,BinTree BST)
      {
          while(BST)
          {
              if(X>BST->Data)
              {
                  BST=BST->Right;//向右子树移动,继续查找
              }
              else if(X<BST->Data)
              {
                  BST=BST->Left;//向左子树移动,继续查找
              }
              else
              {
                  return BST;//查找成功,返回地址
              }
          }
          return NULL;//查找失败
      }
      

    查找的效率决定于树的高度

  2. Position FindMin(BinTree BST):从二叉搜索树BST中查找并返回最小元素所在结点的地址;
    根据二叉搜索树的特点可知,最小元素一定在树的最左分枝的端结点上

    • 递归实现

      Position FindMin(BinTree BST)
      {
          //如果是空树,返回NULL
          if(!BST)
          {
              return BST;
          }
          //如果不是空树,且左子树不为空,向左走
          else if(BST->Left)
          {
              return FindMin(BST->Left);
          }
          //如果不是空树,且左子树为空,此结点就是所求元素结点,返回地址
          else
          {
              return BST;
          }
      }
      
    • 非递归实现

      Position FindMin(BinTree BST)
      {
          //如果二叉树是空的,返回NULL,否者找到最左端结点
          if(BST)
          {
              //一直往左,直到最左的结点
              while(BST->Left)
              {
                  BST=BST->Left;
              }
          }
          return BST;
      }
      
  3. Position FindMax(BinTree BST):从二叉搜索树BST中查找并返回最大元素所在结点的地址;
    根据二叉搜索树的特点可知,最大元素一定在树的最右分枝的端结点上

    • 递归实现

      Position FindMax(BinTree BST)
      {
          //如果是空树,返回NULL
          if(!BST)
          {
              return BST;
          }
          //如果不是空树,且右子树不为空,向右走
          else if(BST->Left)
          {
              return FindMin(BST->Left);
          }
          //如果不是空树,且右子树为空,此结点就是所求元素结点,返回地址
          else
          {
              return BST;
          }
      }
      
    • 非递归实现

      Position FindMax(BinTree BST)
      {
          //如果二叉树是空的,返回NULL,否者找到最右端结点
          if(BST)
          {
              //一直往右,直到最右的结点
              while(BST->Right)
              {
                  BST=BST->Right;
              }
          }
          return BST;
      }
      
  4. BinTree Insert(ElementType X,BinTree BST):将键值为X的结点插入二叉搜索树;

    BinTree Insert(ElementType X,BinTree BST)
    {
        //树是空树,增加一个结点
        if(!BST)
        {
            BST=(BinTree)malloc(sizeof(struct TreeNode));
            BST->Data=X;
            BST->Left=NULL;
            BST->Right=NULL;
        }
        //不是空树,比较根结点和X的大小。
        else
        {
            //X比根结点小,往插入左子树
            if(X<BST->Data)
            {
                BST->Left=Insert(X,BST->Left);
            }
            //X比根结点大,往插入右子树
            else if(X>BST->Data)
            {
                BST->Right=Insert(X,BST->Right);
            }
            //else x已经存在,什么都不做
        }
        return BST;
    }
    
  5. BinTree Delete(ElementType X,BinTree BST):将二叉查找树中键值为X的结点删除。
    考虑三种情况:

    1. 要删除的是叶结点:直接删除,并再修改其父结点指针,置为NULL
    2. 要删除的结点只有一个孩子结点:将其父结点的指针指向要删除结点的孩子结点。
    3. 要删除的结点有左右两棵子树:用右子树的最小元素或者左子树的最大元素替代被删除结点,然后将右子树的最小元素或者左子树的最大元素删除
      这样做的好处右子树的最小元素或者左子树的最大元素一定只有一个儿子结点。
    BinTree Delete(ElementType X,BinTree BST)
    {
        Position Tmp;
        //树里没有要找的元素
        if(!BST)
        {
            printf("要删除的元素未找到\n");
        }
        //左子树递归删除
        else if(X<BST->Data)
        {
            BST->Left=Delete(X,BST->Left);
        }
        //右子树递归删除
        else if(X>BST->Right)
        {
            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);
            }
        }
        return BST;
    }
    
发布了12 篇原创文章 · 获赞 2 · 访问量 787

猜你喜欢

转载自blog.csdn.net/qq_42313728/article/details/100176294
今日推荐