二叉搜索树的查询操作《算法导论》12.2

  • 我们可以在O(h)时间内完成二叉搜索树的查找、最大值、最小值、给定节点的前驱、后继操作,h代表树的高度。下面是用C++实现的《算法导论》12.2节伪代码。
#include <iostream>
#include <queue>
#include <stack>
using namespace std;

struct Node
{
    int   key;
    Node* parent;
    Node* left;
    Node* right;
    Node(int k) :key(k),parent(nullptr),
        left(nullptr),right(nullptr){}
    Node(){}
};

//add a node to the tree rooted at a given node
void add(Node* pRoot, Node* pAdd)
{
    Node *pParent = pRoot, *pTmpParent;
    bool bLeft;
    while(true)
    {
        bLeft = (pAdd->key < pParent->key) ? true : false;
        pTmpParent = bLeft ? pParent->left : pParent->right;
        if(nullptr != pTmpParent)
        {
            pParent = pTmpParent;
            continue;
        }

        pAdd->parent = pParent;
        if(bLeft)
            pParent->left = pAdd;
        else
            pParent->right = pAdd;
        break;
    }
}

/*create the tree, we assume all keys to be distinct
 *                  15
 *       6                      18
 *  3       7               17      20
 * 2 4          13
 *            9
 */
Node* build()
{
    Node* pRoot = new Node(15);
    add(pRoot, new Node(6));
    add(pRoot, new Node(3));
    add(pRoot, new Node(2));
    add(pRoot, new Node(4));
    add(pRoot, new Node(7));
    add(pRoot, new Node(13));
    add(pRoot, new Node(9));
    add(pRoot, new Node(18));
    add(pRoot, new Node(17));
    add(pRoot, new Node(20));
    return pRoot;
}

//destroy the tree
void destroy(Node* pRoot)
{
    std::queue<Node*> q;
    q.push(pRoot);
    Node* p;
    while(!q.empty())
    {
        p = q.front();
        q.pop();
        if(!p)
            continue;
        q.push(p->left);
        q.push(p->right);
        delete p;
    }
}

//inorder tree walk
void walk(Node* pRoot)
{
    stack<Node*> stk;
    stk.push(pRoot);
    while(true)
    {
        Node* pCurrent = stk.top();
        if(pCurrent)
        {
            stk.push(pCurrent->left);
            continue;
        }
        stk.pop();
        if(stk.empty())
            break;
        pCurrent = stk.top();
        cout << pCurrent->key << "\t";
        stk.pop();
        stk.push(pCurrent->right);
    }
}

//recursive search
Node* search(Node* pRoot, int key)
{
    if(!pRoot)
        return  nullptr;
    if(key == pRoot->key)
        return pRoot;
    if(key < pRoot->key)
        return search(pRoot->left, key);
    else
        return search(pRoot->right, key);
}

//nonrecursive search
Node* search1(Node* pRoot, int key)
{
    while(pRoot && key != pRoot->key)
    {
        if(key < pRoot->key)
            pRoot = pRoot->left;
        else
            pRoot = pRoot->right;
    }
    return pRoot;
}

//returns a pointer to the minimum element in the subtree rooted at a given node x, which we assume to be not null
Node* minimum(Node* pRoot)
{
    cout << "minimum in the tree rooted at Node " << pRoot->key << "\tis: ";
    while(pRoot->left != nullptr)
        pRoot = pRoot->left;
    cout << pRoot->key << endl;
    return pRoot;
}

//returns a pointer to the maximum element in the subtree rooted at a given node x, which we assume to be not null
Node* maximum(Node* pRoot)
{
    cout << "manimum in the tree rooted at Node " << pRoot->key << "\tis: ";
    while(pRoot->right != nullptr)
        pRoot = pRoot->right;
    cout << pRoot->key << endl;
    return pRoot;
}

//returns the node with the largest key smaller than p->key in the sorted order
Node* predecessor(Node* p)
{
    if(p->left)
        return maximum(p->left);
    Node* pParent = p->parent;
    while(pParent && p == pParent->left)
    {
        p = pParent;
        pParent = p->parent;
    }
    return pParent;
}

//returns the node with the smallest key greater than p->key in the sorted order
Node* successor(Node* p)
{
    if(p->right)
        return minimum(p->right);
    Node* pParent = p->parent;
    while(pParent && pParent->right == p)
    {
        p = pParent;
        pParent = p->parent;
    }
    return pParent;
}

void testBinarySearchTree()
{
    Node* pRoot = build();
    walk(pRoot);
    cout << endl;
    {
        cout << search(pRoot, 9)->key << endl;
        cout << search(pRoot, 13)->key << endl;
        cout << search1(pRoot, 17)->key << endl;
        cout << search1(pRoot, 4)->key << endl;
    }
    {
        minimum(pRoot);
        minimum(pRoot->right);
        minimum(pRoot->left->right);
    }
    {
        maximum(pRoot);
        maximum(pRoot->right->right);
        maximum(pRoot->left);
    }
    {
        cout << "the predecessor of " << pRoot->key << "\tis: "
        << predecessor(pRoot)->key << endl;
        cout << "the predecessor of " << pRoot->right->left->key << "\tis: "
        << predecessor(pRoot->right->left)->key<< endl;
        cout << "the predecessor of " << pRoot->left->right->key << "\tis: "
        << predecessor(pRoot->left->right)->key << endl;
    }
    {
        cout << "the successor of " << pRoot->key << "\tis: "
        << successor(pRoot)->key << endl;
        cout << "the successor of " << pRoot->right->left->key << "\tis: "
        << successor(pRoot->right->left)->key<< endl;
        cout << "the successor of " << pRoot->left->right->right->key << "\tis: "
        << successor(pRoot->left->right->right)->key << endl;
    }
    destroy(pRoot);
}

/*output:
2   3   4   6   7   9   13  15  17  18  20
9
13
17
4
minimum in the tree rooted at Node 15   is: 2
minimum in the tree rooted at Node 18   is: 17
minimum in the tree rooted at Node 7    is: 7
manimum in the tree rooted at Node 15   is: 20
manimum in the tree rooted at Node 20   is: 20
manimum in the tree rooted at Node 6    is: 13
manimum in the tree rooted at Node 6    is: 13
the predecessor of 15   is: 13
the predecessor of 17   is: 15
the predecessor of 7    is: 6
minimum in the tree rooted at Node 18   is: 17
the successor of 15 is: 17
the successor of 17 is: 18
the successor of 13 is: 15
*/

猜你喜欢

转载自www.cnblogs.com/meixiaogua/p/9877203.html