- 我们可以在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
*/