CLRS 12.4隨機構建二叉搜索樹

12.4-1
證明前先需要知道有 (44)=(33) 以及附錄 C 的練習 C.1-7 需要證明的等式 (nk)=(n1k)+(n1k1)
先證明附錄 C 的練習 C.1-7

(n1k)+(n1k1)=(n1)!k!(n1k)!+(n1)!(k1)!(n1k+1)!=(n1k+1)(n1)!k!(n1k+1)!+k(n1)!k!(n1k+1)!=(n1k+1+k)(n1)!k!(n1k+1)!=n!k!(nk)!=(nk)

然後有:
i=0n1(i+33)=(44)+i=1n1(i+33)=(44)+(43)+(53)++(n+23)=(54)+(53)++(n+23)=(n+34)

12.4-2
首先給出第二個問題的答案,即漸進上界 O(nlgn) 。證明略,可以參考算法導論指導手冊上此題的證明。
下面給出一個例子,n 個結點的平均深度 Θ(lgn) 但高度是 ω(lgn) 。其中 nnlgn 個結點是完全二叉樹,剩下的是一條單鏈,高度爲:
Θ(lg(nnlgn))+nlgn=Θ(nlgn)=ω(lgn)
這裏寫圖片描述
對此例的平均深度證明是 Θ(lgn) 同樣略過。

12.4-3
先給出 n=3 構建出來的全部二叉搜索樹。
這裏寫圖片描述
從左到右依次編號爲 1,2,3,4,5
1;2;3 對應圖1;
1;3;2 對應圖2;
2;1;32;3;1 對應圖3;
3;2;1 對應圖4;
3;1;2 對應圖5。
因此圖3被創建的概率是 2/6 ,其餘的是 1/6 。而隨機構建二叉搜索樹都是 1/5

12.4-4
在書的附錄裏面有凸函數的定義(見中文版第三版的P701或英文版的P1199),然後國外的語意和國內相反,所以我們是要證明 f(x)=2x 是凹函數。
證明:根據凹函數定義:對於任意 x,y,λ(0,1) ,有 λ2x+(1λ)2y2(λx+(1λ)y) ……①
這裏有個重要不等式,即對於任意 a,b,c 都有 cacb+(ab)(cb)lnc 。在這簡單證明一下,根據 ex1+x 有:設 x=(ab)lnc 帶入 e((ab)lnc)1+(ab)lncc(ab)1+(ab)lnc 兩邊都乘以 cb 即得證。
這樣用 2 代替 c,x 代替 a,z 代替 b ,其中 z=λx+(1λ)y
帶入並化解得:2x2z+(xz)(2z) ….②同理,ay 其他一樣,得 2y2z+(yz)(2z) ….③。
把②和③式帶入①式得:

λ2x+(1λ)2yλ(2z+(xz)(2z))+(1λ)(2z+(yz)(2z))=(λ+1λ)2z+(λ(xz)+(1λ)(yz))(2z)

由於 (λ(xz)+(1λ)(yz))=0 ,所以 λ2x+(1λ)2y2z=2(λx+(1λ)y) ,得證!

12.4-5
略。



附上本章的一些實現代碼

#include <iostream>
#include <stack>
using std::cout;
using std::endl;
using std::stack;

struct BinTree
{
    int key;
    BinTree *parent;
    BinTree *left;
    BinTree *right;
};

void preOrder(BinTree *root)
{
    if(root != NULL)
    {
        cout << root->key << ' ';
        preOrder(root->left);
        preOrder(root->right);
    }
}

void non_recursive_preOrder(BinTree *root)
{
    stack<BinTree *> ptr;
    ptr.push(root);
    while(root != NULL && !ptr.empty())
    {
        BinTree *p = ptr.top();
        cout << p->key << ' ';
        ptr.pop();
        if(p->right != NULL)
            ptr.push(p->right);
        if(p->left != NULL)
            ptr.push(p->left);
    }
}

void inOrder(BinTree *root)
{
    if(root != NULL)
    {
        inOrder(root->left);
        cout << root->key << ' ';
        inOrder(root->right);
    }
}

void non_recursive_inOrder(BinTree *root)
{
    stack<BinTree *> ptr;
    BinTree *p = root;
    while(p != NULL || !ptr.empty())
    {
        while(p != NULL)    //找到最左孩子
        {
            ptr.push(p);
            p = p->left;
        }
        if(!ptr.empty())    //彈出,然後向右
        {
            p = ptr.top();
            ptr.pop();
            cout << p->key << ' ';
            p = p->right;
        }
    }
}

void postOrder(BinTree *root)
{
    if(root != NULL)
    {
        postOrder(root->left);
        postOrder(root->right);
        cout << root->key << ' ';
    }
}

void non_recursive_postOrder(BinTree *root)
{
    stack<BinTree *> ptr;
    BinTree *cur;
    BinTree *pre = NULL;
    ptr.push(root);
    while(!ptr.empty())
    {
        cur = ptr.top();
        //當前結點沒孩子或者左(右)孩子已經訪問過,則訪問當前結點
        if(cur->left == NULL && cur->right == NULL || pre != NULL && (pre == cur->left || pre == cur->right))
        {
            cout << cur->key << ' ';
            ptr.pop();
            pre = cur;
        }
        else
        {
            if(cur->right != NULL)
                ptr.push(cur->right);
            if(cur->left != NULL)
                ptr.push(cur->left);
        }
    }
}

BinTree *TREE_SEARCH(BinTree *root,int value)
{
    if(root == NULL)
        return root;
    if(root->key == value)
        return root;
    if(root->key < value)
        TREE_SEARCH(root->right,value);
    else TREE_SEARCH(root->left,value);
}

BinTree *non_recursive_TREE_SEARCH(BinTree *root,int value)
{
    while(root != NULL && root->key != value)
    {
        if(root->key < value)
            root = root->right;
        else root = root->left;
    }
    return root;
}

BinTree *TREE_MINIMUM(BinTree *root)
{
    if(root == NULL)
        return root;
    if(root->left == NULL)
        return root;
    else return TREE_MINIMUM(root->left);
}

BinTree *non_recursive_TREE_MINIMUM(BinTree *root)
{
    if(root == NULL)
        return root;
    while(root->left != NULL)
        root = root->left;
    return root;
}

BinTree *TREE_MAXIMUM(BinTree *root)
{
    if(root == NULL)
        return root;
    if(root->right == NULL)
        return root;
    else return TREE_MAXIMUM(root->right);
}

BinTree *non_recursive_TREE_MAXIMUM(BinTree *root)
{
    if(root == NULL)
        return root;
    while(root->right != NULL)
        root = root->right;
    return root;
}

BinTree *TREE_SUCCESSOR(BinTree *p)
{
    if(p == NULL)
        return p;
    if(p->right != NULL)
        return TREE_MINIMUM(p->right);
    BinTree *x = p->parent;
    while(x != NULL && p == x->right)
    {
        p = x;
        x = x->parent;
    }
    return x;
}

BinTree *TREE_PREDECESSOR(BinTree *p)
{
    if(p == NULL)
        return p;
    if(p->left != NULL)
        return TREE_MAXIMUM(p->left);
    BinTree *x = p->parent;
    while(x != NULL && p == x->left)
    {
        p = x;
        x = x->parent;
    }
    return x;
}

void TREE_INSERT(BinTree **root,int key)
{
    if(*root == NULL)   //插入根節點
    {
        BinTree *z = new BinTree;
        z->key = key;
        z->left = z->right = NULL;
        *root = z;
        z->parent = NULL;
        return;
    }
    BinTree *x = *root;
    if(x->key > key)    //左子樹
    {
        if(x->left == NULL) //左子樹爲空
        {
            BinTree *z = new BinTree;
            z->key = key;
            z->left = z->right = NULL;
            z->parent = x;
            x->left = z;
        }
        else TREE_INSERT(&(x->left),key);//以左子樹爲根遞歸插入
    }
    else        //右子樹
    {
        if(x->right == NULL)
        {
            BinTree *z = new BinTree;
            z->key = key;
            z->left = z->right = NULL;
            z->parent = x;
            x->right = z;
        }
        else TREE_INSERT(&(x->right),key);
    }
}

void non_recursive_TREE_INSERT(BinTree **root,int key)
{
    BinTree *z = new BinTree;
    z->key = key;
    z->left = z->right = NULL;
    BinTree *y = NULL;
    BinTree *x = *root;
    while(x != NULL)
    {
        y = x;
        if(x->key < z->key)
            x = x->right;
        else x = x->left;
    }
    z->parent = y;
    if(y == NULL)
        *root = z;
    else if(y->key < z->key)
        y->right = z;
    else y->left = z;
}

void TRANSPLANT(BinTree **root,BinTree *u,BinTree *v)
{
    if(u->parent == NULL)
        *root = v;
    else if(u == u->parent->left)
        u->parent->left = v;
    else u->parent->right = v;
    if(v != NULL)
        v->parent = u->parent;
}

void TREE_DELETE(BinTree **root,int key)
{
    BinTree *p = TREE_SEARCH(*root,key);
    if(p == NULL)
        return;
    if(p->left == NULL)
        TRANSPLANT(root,p,p->right);
    else if(p->right == NULL)
        TRANSPLANT(root,p,p->left);
    else{
        BinTree *y = TREE_MINIMUM(p->right);
        if(y->parent != p)
        {
            TRANSPLANT(root,y,y->right);
            y->right = p->right;
            y->right->parent = y;
        }
        TRANSPLANT(root,p,y);
        y->left = p->left;
        y->left->parent = y;
    }
    delete p;
}

int main()
{
    BinTree *root = NULL;
    int array[] = {8,2,-5,1,77,-6,45,0,5};
    for(int i = 0; i < 5; ++i)
        TREE_INSERT(&root,array[i]);    //創建樹
    for(int i = 5; i < 9; ++i)
        non_recursive_TREE_INSERT(&root,array[i]);  //接上繼續創建,在這只是爲了測試

    //分別用先中後序輸出,包括每種順序的遞歸和非遞歸
    cout << "preOrder: ";
    preOrder(root);
    cout << endl;
    cout << "non recursive preOrder: " ;
    non_recursive_preOrder(root);
    cout << endl;
    cout << "inOrder: " ;
    inOrder(root);
    cout << endl;
    cout << "non recursive inOrder: ";
    non_recursive_inOrder(root);
    cout << endl;
    cout << "postOrder: ";
    postOrder(root);
    cout << endl;
    cout << "non recursive postOrder: ";
    non_recursive_postOrder(root);
    cout << endl;

    //查找元素,找到則輸出並找到該元素的前驅和後繼
    BinTree *p = TREE_SEARCH(root,77);
    if(p != NULL){
        cout << "find " << p->key << endl;
        cout << "it's predecessor and successor: ";
        BinTree *pre = TREE_PREDECESSOR(p);
        if(pre != NULL)
            cout << pre->key << ' ';
        else cout << "NULL" << ' ';
        BinTree *succ = TREE_SUCCESSOR(p);
        if(succ != NULL)
            cout << succ->key << ' ';
        else cout << "NULL" << ' ';
        cout << endl;
    }
    else cout << "can not find in the tree" << endl;
    p = TREE_SEARCH(root,66);
    if(p != NULL){
        cout << "find " << p->key << endl;
        cout << "it's predecessor and successor: ";
        BinTree *pre = TREE_PREDECESSOR(p);
        if(pre != NULL)
            cout << pre->key << ' ';
        else cout << "NULL" << ' ';
        BinTree *succ = TREE_SUCCESSOR(p);
        if(succ != NULL)
            cout << succ->key << ' ';
        else cout << "NULL" << ' ';
        cout << endl;
    }
    else cout << "can not find in the tree" << endl;
    p = TREE_SEARCH(root,8);
    if(p != NULL){
        cout << "find " << p->key << endl;
        cout << "it's predecessor and successor: ";
        BinTree *pre = TREE_PREDECESSOR(p);
        if(pre != NULL)
            cout << pre->key << ' ';
        else cout << "NULL" << ' ';
        BinTree *succ = TREE_SUCCESSOR(p);
        if(succ != NULL)
            cout << succ->key << ' ';
        else cout << "NULL" << ' ';
        cout << endl;
    }
    else cout << "can not find in the tree" << endl;

    //找到樹的最小和最大值
    p = TREE_MINIMUM(root);
    if(p != NULL)
        cout << "minimum is: " << p->key << endl;
    p = TREE_MAXIMUM(root);
    if(p != NULL)
        cout << "maximum is: " << p->key << endl;

    //刪除操作
    TREE_DELETE(&root,8);
    p = TREE_SEARCH(root,8);
    if(p != NULL){
        cout << "find " << p->key << endl;
        cout << "it's predecessor and successor: ";
        BinTree *pre = TREE_PREDECESSOR(p);
        if(pre != NULL)
            cout << pre->key << ' ';
        else cout << "NULL" << ' ';
        BinTree *succ = TREE_SUCCESSOR(p);
        if(succ != NULL)
            cout << succ->key << ' ';
        else cout << "NULL" << ' ';
        cout << endl;
    }
    else cout << "can not find in the tree" << endl;

    //刪除後中序遍歷
    inOrder(root);
    cout << endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章