1. 程式人生 > >833系列——二叉排序樹

833系列——二叉排序樹

tree src 我們 不用 emp 刪除 假設 cout inf

考綱中,二叉排序樹在“查找”章節,要求為:二叉排序樹及其基本操作。

其基本操作有:查找操作,插入操作,刪除操作


一:定義

二叉排序樹(Binary Sort Tree),又稱二叉查找樹,它是一顆空樹,或者是具有以下性質的二叉樹:

若它的左子樹不空,則左子樹上所有結點的值均小於它的根節點的值。

若它的右子樹不空,則右子樹上所有結點的值均大於它的根節點的值。

它的左右子樹也都是二叉排序樹

二:首先定義一個二叉樹的結構

 1 struct BSTree
 2 {
 3     int data;
 4     BSTree *lchild, *rchild;
5 BSTree(int d = 0, BSTree *l = NULL, BSTree *r = NULL) 6 { 7 data = d; 8 lchild = l; 9 rchild = r; 10 } 11 };

三:建立一個二叉排序樹

二叉排序樹的建立,其實就是由一個空樹,一個一個的插入數據形成的,也就是需要插入操作

而在插入操作中,我們需要找到插入數據合適的位置,這裏又可以看做是查找操作

插入操作有遞歸和循環兩種寫法

循環寫法:

void insertTree1(BSTree* &root, int
key) { if(root == NULL) { BSTree *s = new BSTree(key); root = s; return; } BSTree *t = root; while(t->data != key) { if(key > t->data && t->rchild != NULL) t = t->rchild; else if(key < t->data && t->lchild != NULL) t
= t->lchild; else if(key > t->data && t->rchild == NULL) { BSTree *s = new BSTree(key); t->rchild = s; } else if(key < t->data && t->lchild == NULL) { BSTree *s = new BSTree(key); t->lchild = s; } } }

遞歸寫法:

void insertTree2(BSTree* &root, int key)
{
    if(root == NULL)
    {
        BSTree *s = new BSTree(key);
        root = s;
        return;
    }
    if(key > root->data)
        insertTree2(root->rchild, key);
    else
        insertTree2(root->lchild,key);
}

查找操作由插入操作簡單修改得到,不再上代碼

四:刪除操作(重點)

刪除節點有三種情況:

要刪除的點為葉子節點,直接刪除即可;

要刪除的點只有左子樹,或只有右子樹,刪除節點後,將左子樹或右子樹整體移動到被刪除節點的位置即可;

要刪除的節點即有左子樹,又有右子樹;

第一、二種情況可以合並為第二種,第三種情況比較復雜

根據二叉排序樹的定義,節點刪除後,這個位置應該由與它大小相鄰的數代替,對於下面這張圖:

技術分享圖片

假設要刪除的節點為47,那麽能夠代替這個位置的就是37和48,可以發現,這兩個數都有一個特點,37為47的左子樹中的最右子樹,48為47的右子樹的最左子樹

基於此可以這樣做:假定每次都用較小的數來代替,也就是37,此時51這邊整體就不用動了,只需要將37移動到47的位置,然後將37的整個左子樹移動到37原來的位置

代碼:

void Delete(BSTree* &node)
{
    if(node->lchild == NULL)
    {
        BSTree *temp = node;
        node = node->rchild;
        delete(temp);
    }
    else if(node->rchild == NULL)
    {
        BSTree *temp = node;
        node = node->lchild;
        delete(temp);
    }
    else //用與該節點臨近且小於的點代替
    {
        BSTree *newnode = node->lchild;
        BSTree *temp = node;
        while(newnode->rchild != NULL)
        {
            temp = newnode;
            newnode = newnode->rchild;
        }
        node->data = newnode->data;
        if(temp != node)
            temp->rchild = newnode->lchild;
        else
            temp->lchild = newnode->lchild;
        delete(newnode);
    }
}
void DeleteTree(BSTree* &root, int key)
{
    if(root == NULL)
        return;
    if(key == root->data)
        Delete(root);
    else if(key > root->data)
        return DeleteTree(root->rchild, key);
    else
        return DeleteTree(root->lchild, key);
}

五:遍歷及測試數據

建好二叉排序樹後,使用中序遍歷,即可得到一個排好序的數列

void InOrder(BSTree *root)
{
    if(root != NULL)
    {
        InOrder(root->lchild);
        cout << root->data << " ";
        InOrder(root->rchild);
    }
}

測試數據

int main()
{
    int a[12] = {29, 36, 62, 88, 58, 47, 35, 73, 51, 99, 37, 93};
    BSTree *root = NULL;
    for(int i=0; i<12; i++)
    {
        insertTree2(root, a[i]);
    }
    InOrder(root);
    cout << endl;
    DeleteTree(root, 47);
    InOrder(root);
    return 0;
}

833系列——二叉排序樹