【數據結構】搜索二叉樹

手寫實現搜索二叉樹:


  • 樹的節點定義:
class TreeNode
{
public:
    TreeNode(int v) :value(v){};

    TreeNode* left_son = NULL;
    TreeNode* right_son = NULL;
    TreeNode* p = NULL;         //一定保存雙親的指針
    int value = 0;
};

  • 節點插入:
bool TreeInsert(TreeNode*& pRoot,int value)
{
    TreeNode* pNew = new TreeNode(value);//待插入的節點
    TreeNode* pParent = NULL;//父節點
    TreeNode* pCur = pRoot;//子節點
    while (pCur != NULL)
    {
        pParent = pCur;
        if (pCur->value < value)
        {
            pCur = pCur->right_son;
        }
        else if (pCur->value>value)
        {
            pCur = pCur->left_son;
        }
        else
        {
            return false;
        }
    }
    if (pParent == NULL)//空樹
    {
        pRoot = pNew;
    }
    else if ( pParent->value<value )//插右邊
    {
        pParent->right_son = pNew;
        pNew->p = pParent;
    }
    else//插左邊
    {
        pParent->left_son = pNew;
        pNew->p = pParent;
    }
    return true;
}

  • 最大值,最小值函數
TreeNode* TreeMax(TreeNode* pRoot)
{
    while (pRoot!=NULL&&pRoot->right_son!=NULL)
    {
        pRoot = pRoot->right_son;
    }
    return pRoot;
}

TreeNode* TreeMin(TreeNode* pRoot)
{
    while (pRoot!=NULL&&pRoot->left_son!=NULL)
    {
        pRoot = pRoot->left_son;
    }
    return pRoot;
}

  • 前驅、後繼函數
TreeNode* Successor(TreeNode* pRoot)
{
    /*
    尋找節點的後繼節點
    方法一:中序遍歷,後繼即 該節點輸出的後一個節點
    方法二:若當前節點有右孩子,則後繼爲右孩子子樹的最小節點
            若當前節點無右孩子,則後繼爲其最底層的祖先,條件是該結點位於此祖先的左子樹
    */
    if (pRoot==NULL)
    {
        return pRoot;
    }
    if (pRoot->right_son != NULL)// 當前節點有右孩子
    {
        return TreeMin(pRoot->right_son);
    }

    TreeNode* pChild = pRoot;
    TreeNode* pParent = pChild->p;

    while (pParent != NULL&&pParent->right_son == pChild)//當前節點無右孩子,尋找滿足要求的最底層祖先
    {
        pChild = pParent;
        pParent = pParent->p;
    }
    return pParent;
}

TreeNode* Processor(TreeNode* pRoot)
{
    /*
    尋找節點的前驅節點
    若當前節點有左孩子,則前驅爲左孩子子樹的最大節點
    若當前節點無左孩子,則後繼爲其最底層的祖先,條件是該結點位於此祖先的右子樹
    */
    if (pRoot == NULL)
    {
        return pRoot;
    }
    if (pRoot->left_son != NULL)//有左孩子
    {
        return TreeMax(pRoot->left_son);
    }

    TreeNode* pChild = pRoot;
    TreeNode* pParent = pChild->p;

    while (pParent != NULL&&pParent->left_son == pChild)//無左孩子,尋找滿足要求的最底層祖先
    {
        pChild = pParent;
        pParent = pParent->p;
    }
    return pParent;
}

  • 替換函數,使用一棵樹接管另一棵樹的雙親
bool TransPlant(TreeNode *& pRoot, TreeNode* pOld, TreeNode* pNew)
{
    /*
    使用一棵樹接管另一棵樹的雙親
    */
    if (pRoot == NULL||pOld == NULL)//舊子樹爲空
    {
        return false;
    }

    //調整父節點的指針
    if (pOld->p == NULL)//父節點爲空:替換了根節點
    {
        pRoot = pNew;
    }
    else
    {
        if (pOld == pOld->p->left_son)
        {
            pOld->p->left_son = pNew;
        }
        else
        {
            pOld->p->right_son = pNew;
        }
    }
    //調整指向父節點的指針
    if (pNew != NULL)//新子樹不爲空
    {
        pNew->p = pOld->p;
    }
    return true;
}
  • 刪除節點
void TreeDelete(TreeNode*& pRoot, TreeNode* pDelete)
{
    /*
    刪除指定節點
    */
    if (pRoot == NULL || pDelete == NULL)
        return;

    if (pDelete->left_son == NULL)//沒有孩子或者只有一個孩子,直接將孩子提上來
    {
        TransPlant(pRoot,pDelete, pDelete->right_son);
    }
    else if (pDelete->right_son == NULL)
    {
        TransPlant(pRoot,pDelete, pDelete->left_son);
    }
    else//同時有兩個孩子時
    {
        TreeNode* successor = TreeMin(pDelete->right_son);//尋找後繼,後繼一定沒有左孩子節點

        if (successor->p != pDelete)//後繼不是被刪除節點的右孩子節點
        {
            TransPlant(pRoot,successor, successor->right_son);//刪除後繼節點
            successor->right_son = pDelete->right_son;//將後繼提到被刪除節點右孩子位置上:接管被刪除節點的右孩子
            successor->right_son->p = successor;
        }

        TransPlant(pRoot,pDelete, successor);//後繼接管被刪節點的雙親
        successor->left_son = pDelete->left_son;//後繼接管被刪節點的左孩子
        successor->left_son->p = successor;
    }
}

  • 中序打印函數
  • 測試主函數
void TreePrint(TreeNode* pRoot)
{
    if (pRoot == NULL)
    {
        return;
    }
    TreePrint(pRoot->left_son);
    cout << pRoot->value << " ";
    TreePrint(pRoot->right_son);
}

int main()
{
    TreeNode* pRoot(NULL);
    TreeInsert(pRoot, 4);
    TreeInsert(pRoot, 1);
    TreeInsert(pRoot, 9);
    TreeInsert(pRoot, 2);
    TreeInsert(pRoot, 8);
    TreeInsert(pRoot, 3);
    TreeInsert(pRoot, 6);

    TreePrint(pRoot);
    cout << endl;
    TreeDelete(pRoot,pRoot);
    TreePrint(pRoot);

    return 0;

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章