1. 程式人生 > >二叉排序樹(BST)問題

二叉排序樹(BST)問題

昨天晚上和RE聊完天之後,單JJ問了我一個二叉排序樹問題,那個題目不難,就是給一個了一棵二叉排序樹作為模型,有給了若干棵二叉排序樹,問這幾棵樹和模型樹是否是同一棵樹。這麼一個小問題搞了半個小時,簡直了。這個題目只需要寫一個BST建樹函式和求前序和中序的函式(一棵唯一的樹有唯一的前中序或中後序),然後對模型樹和這若干樹進行前中序比較,如果完全相同,就可以判斷為同一棵樹。 昨天才發現沒有寫過二叉排序樹的建樹,也發現《資料結構》木有講二叉排序樹,今天算是總結一些BST問題。

什麼BST

二叉排序樹(Binary Sort Tree)又稱二叉查詢樹(Binary Search Tree),亦稱二叉搜尋樹。 它或者是一棵空樹;或者是具有下列性質的二叉樹: (1)若左子樹不空,則左子樹上所有結點的值均小於它的根結點的值; (2)若右子樹不空,則右子樹上所有結點的值均大於它的根結點的值; (3)左、右子樹也分別為二叉排序樹; 又是一個遞迴的定義。

說白了,就是:左孩子的二叉樹。 也就是因為BST的特性,導致他在元素查詢的時候比普通二叉樹更有優勢(有點像二分),但整棵樹要滿足這個性質,也註定讓BST在建立和刪除的時候和普通二叉樹不一樣。

BST的插入

BST的插入是建立BST的基礎,在插入一棵BST的時候一定要注意滿足左

void inst(node *rt,node *root)
{
    if(rt->data data)
    {
        if(root->lc == NULL)
            root->lc = rt;
        inst(rt,root->lc);
    }else
    {
        if(root->rc == NULL)
            root->rc = rt;
        inst(rt,root->rc);
    }
}

建立BST

建立BST是在插入BST的基礎上的,因為建立一棵BST的過程就是一個一個將結點插入到樹的過程。

node *build(char *s)
{
    node *root = NULL;
    while(*s !='�')
    {
        node *rt = new node;
        rt->data = *(s++);
        rt->lc = NULL;
        rt->rc = NULL;
        if(root == NULL)
            root = rt;
        else
            inst(rt,root);
    }

    return root;
}

BST的查詢

BST也被稱為二叉查詢樹的原因就是它的查詢優勢,二分,在每經過一個結點的時候,可以放棄樹的另一枝而不用遍歷整棵樹。

node *findnode(int data,node *root)
{
    if(root == NULL)
        return NULL;

    if(data == root->data)
        return root;
    else if(data data)
        return findnode(data,root->lc);
    else
        return findnode(data,root->rc);
}

BST的刪除

BST的整棵樹的刪除還是很簡單的,一個遞迴,和刪除整個二叉樹一樣,難的是刪除BST的一個結點。

刪除整棵樹

void deltree(node *root)
{
    if(root == NULL)
        return ;

    deltree(root->lc);
    deltree(root->rc);
    delete(root);
}

 刪除結點

刪除結點是建立在查詢的基礎上的,

node *finddlenode(int data,node *root)
{
 if(root)
 {
 if(data == root->data)
 root = delnode(root);
 else if(data data)
 root->lc = finddelnode(data,root->lc);
 else
 root->rc = finddelnode(data,root->rc);
 }

 return root;
}

刪除結點,對於BST來講,就會破壞整棵樹的規律,那麼當我們刪除一個結點之後,可能會遇到4種情況

  • 刪除的是葉子,還是一棵BST
  • 刪除的結點只有左孩子
  • 刪除的結點只有右孩子
  • 刪除的結點有兩個孩子

對於第一種情況,很好辦,可以不用考慮,第二種情況以及以後,如果簡單考慮,可以認為變成了2-3個BST森林,我們只需要再把它們合成一棵樹便好。 對於再把這幾棵樹合成一棵樹,有兩種方法(都是利用右枝比根結點大的特殊性) 方法一:

  1. 若p有左子樹,找到其左子樹的最右邊的葉子結點r,用該葉子結點r來替代p,把r的左孩子作為r的父親的右孩子(相當於把r的右枝移上去而把左枝留在原有位置)。
  2. 若p沒有左子樹,直接用p的右孩子取代它。

方法二:

  1. 若p有左子樹,用p的左孩子取代它;找到其左子樹的最右邊的葉子結點r,把p的右子樹作為r的右子樹。
  2. 若p沒有左子樹,直接用p的右孩子取代它。

兩種方法都不錯,第一種感覺更簡單些。 第一種程式碼

node * delNode(node *root)
{
    node *rnt;
      if (root->lc)
      {
        node *rt = root->lc;   //rt指向其左子樹;
        while(rt->rc != NULL)//搜尋左子樹的最右邊的葉子結點rt
        {
            rt = rt->rc;
        }
            rt->rc = root->rc;

            rnt = root->lc;   //rnt指向其左子樹;
      }
      else
      {
            rnt = root->rc;   //rnt指向其右子樹;
      }
    delete(root);
    return rnt;
}

歡迎到微信裡去當吃瓜群眾