二叉搜索树是以一棵二叉树来组织的,这样一棵树可以用一个链表数据结构来表示,其中每个结点就是一个对象。
二叉搜索树种的关键字总是以满足二叉搜索树的性质的方式来存储,一个结点的左子树中任意结点的键值不大于该结点的键值,且其右子树中任意结点树键值不小于该结点的键值。
如果按照中序遍历的方式输出一棵二叉搜索树的键值,所得到的是一个有序排列的队列。
BinarySearchTree.h
#pragma once
struct BinarySearchTreeNode
{
BinarySearchTreeNode(int key) :Parent(nullptr), Left(nullptr), Right(nullptr), Key(key) { }
BinarySearchTreeNode* Parent;
BinarySearchTreeNode* Left;
BinarySearchTreeNode* Right;
int Key;
void Print();
};
class BinarySearchTree
{
public:
BinarySearchTree();
~BinarySearchTree();
void Report();
void InorderTreeWalk(BinarySearchTreeNode* x);
void PreorderTreeWalk(BinarySearchTreeNode* x);
void PostorderTreeWalk(BinarySearchTreeNode* x);
BinarySearchTreeNode* Minimum(BinarySearchTreeNode* x);
BinarySearchTreeNode* Maximum(BinarySearchTreeNode* x);
BinarySearchTreeNode* Search(BinarySearchTreeNode* x, int key);
BinarySearchTreeNode* IterativeSearch(BinarySearchTreeNode* x, int key);
BinarySearchTreeNode* Successor(BinarySearchTreeNode* x);
BinarySearchTreeNode* Predecessor(BinarySearchTreeNode* x);
void Insert(BinarySearchTreeNode* z);
void Delete(BinarySearchTreeNode* z);
private:
void Release(BinarySearchTreeNode* x);
void Transplant(BinarySearchTreeNode* u, BinarySearchTreeNode* v);
public:
BinarySearchTreeNode* Root;
};
void PrintNode(BinarySearchTreeNode* node);
void TestBinarySearchTree();
BinarySearchTree.cpp
#include "BinarySearchTree.h"
#include <iostream>
#include <vector>
using namespace std;
void BinarySearchTreeNode::Print()
{
cout << Key << " ";
}
BinarySearchTree::BinarySearchTree()
:Root(nullptr)
{
}
BinarySearchTree::~BinarySearchTree()
{
if (Root != nullptr)
{
Release(Root);
}
Root = nullptr;
}
void BinarySearchTree::Report()
{
cout << "PreorderTreeWalk:\t";
PreorderTreeWalk(Root);
cout << endl << "InorderTreeWalk:\t";
InorderTreeWalk(Root);
cout << endl << "PostorderTreeWalk:\t";
PostorderTreeWalk(Root);
cout << endl;
}
void BinarySearchTree::InorderTreeWalk(BinarySearchTreeNode* x)
{
if (x != nullptr)
{
InorderTreeWalk(x->Left);
x->Print();
InorderTreeWalk(x->Right);
}
}
void BinarySearchTree::PreorderTreeWalk(BinarySearchTreeNode* x)
{
if (x != nullptr)
{
x->Print();
PreorderTreeWalk(x->Left);
PreorderTreeWalk(x->Right);
}
}
void BinarySearchTree::PostorderTreeWalk(BinarySearchTreeNode* x)
{
if (x != nullptr)
{
PostorderTreeWalk(x->Left);
PostorderTreeWalk(x->Right);
x->Print();
}
}
BinarySearchTreeNode* BinarySearchTree::Minimum(BinarySearchTreeNode* x)
{
while (x->Left != nullptr)
{
x = x->Left;
}
return x;
}
BinarySearchTreeNode* BinarySearchTree::Maximum(BinarySearchTreeNode* x)
{
while (x->Right != nullptr)
{
x = x->Right;
}
return x;
}
BinarySearchTreeNode* BinarySearchTree::Search(BinarySearchTreeNode* x, int key)
{
if (x == nullptr || key == x->Key)
{
return x;
}
if (key < x->Key)
{
return Search(x->Left, key);
}
else
{
return Search(x->Right, key);
}
}
BinarySearchTreeNode* BinarySearchTree::IterativeSearch(BinarySearchTreeNode* x, int key)
{
while (x != nullptr && key != x->Key)
{
if (key < x->Key)
{
x = x->Left;
}
else
{
x = x->Right;
}
}
return x;
}
BinarySearchTreeNode* BinarySearchTree::Successor(BinarySearchTreeNode* x)
{
if (x->Right != nullptr)
{
return Minimum(x->Right);
}
auto y = x->Parent;
while (y != nullptr && x == y->Right)
{
x = y;
y = y->Parent;
}
return y;
}
BinarySearchTreeNode* BinarySearchTree::Predecessor(BinarySearchTreeNode* x)
{
if (x->Left != nullptr)
{
return Maximum(x->Left);
}
auto y = x->Parent;
while (y != nullptr && x == y->Left)
{
x = y;
y = y->Parent;
}
return y;
}
void BinarySearchTree::Insert(BinarySearchTreeNode* z)
{
BinarySearchTreeNode* x = Root;
BinarySearchTreeNode* y = nullptr;
while (x != nullptr)
{
y = x;
if (z->Key < x->Key)
{
x = x->Left;
}
else
{
x = x->Right;
}
}
z->Parent = y;
if (y == nullptr)
{
Root = z;
}
else if (z->Key < y->Key)
{
y->Left = z;
}
else
{
y->Right = z;
}
}
void BinarySearchTree::Delete(BinarySearchTreeNode* z)
{
if (z->Left == nullptr)
{
Transplant(z, z->Right);
}
else if (z->Right == nullptr)
{
Transplant(z, z->Left);
}
else
{
BinarySearchTreeNode* y = Minimum(z->Right);
if (y->Parent != z)
{
Transplant(y, y->Right);
y->Right = z->Right;
y->Right->Parent = y;
}
Transplant(z, y);
y->Left = z->Left;
y->Left->Parent = y;
}
}
void BinarySearchTree::Release(BinarySearchTreeNode* x)
{
if (x != nullptr)
{
Release(x->Left);
Release(x->Right);
delete x;
}
}
void BinarySearchTree::Transplant(BinarySearchTreeNode* u, BinarySearchTreeNode* v)
{
if (u->Parent == nullptr)
{
Root = v;
}
else if (u == u->Parent->Left)
{
u->Parent->Left = v;
}
else
{
u->Parent->Right = v;
}
if (v != nullptr)
{
v->Parent = u->Parent;
}
}
void PrintNode(BinarySearchTreeNode* node)
{
if (node)
{
node->Print();
}
else
{
cout << "Empty BinarySearchTreeNode." << endl;
}
}
void TestBinarySearchTree()
{
vector<BinarySearchTreeNode*> nodes;
nodes.push_back(new BinarySearchTreeNode(4));
nodes.push_back(new BinarySearchTreeNode(5));
nodes.push_back(new BinarySearchTreeNode(7));
nodes.push_back(new BinarySearchTreeNode(6));
nodes.push_back(new BinarySearchTreeNode(3));
nodes.push_back(new BinarySearchTreeNode(1));
nodes.push_back(new BinarySearchTreeNode(2));
BinarySearchTree* tree = new BinarySearchTree();
for (auto node : nodes)
{
tree->Insert(node);
tree->Report();
}
cout << endl << "Root:\t";
PrintNode(tree->Root);
cout << endl << "Minimum:\t";
PrintNode(tree->Minimum(tree->Root));
cout << endl << "Maximum:\t";
PrintNode(tree->Maximum(tree->Root));
cout << endl << "Search:\t";
PrintNode(tree->Search(tree->Root, 6));
cout << endl << "Successor:\t";
PrintNode(tree->Successor(tree->Root));
cout << endl << "Predecessor:\t";
PrintNode(tree->Predecessor(tree->Root));
cout << endl << endl;
for (auto node : nodes)
{
tree->Report();
tree->Delete(node);
}
}
输出:
PreorderTreeWalk: 4
InorderTreeWalk: 4
PostorderTreeWalk: 4
PreorderTreeWalk: 4 5
InorderTreeWalk: 4 5
PostorderTreeWalk: 5 4
PreorderTreeWalk: 4 5 7
InorderTreeWalk: 4 5 7
PostorderTreeWalk: 7 5 4
PreorderTreeWalk: 4 5 7 6
InorderTreeWalk: 4 5 6 7
PostorderTreeWalk: 6 7 5 4
PreorderTreeWalk: 4 3 5 7 6
InorderTreeWalk: 3 4 5 6 7
PostorderTreeWalk: 3 6 7 5 4
PreorderTreeWalk: 4 3 1 5 7 6
InorderTreeWalk: 1 3 4 5 6 7
PostorderTreeWalk: 1 3 6 7 5 4
PreorderTreeWalk: 4 3 1 2 5 7 6
InorderTreeWalk: 1 2 3 4 5 6 7
PostorderTreeWalk: 2 1 3 6 7 5 4
Root: 4
Minimum: 1
Maximum: 7
Search: 6
Successor: 5
Predecessor: 3
PreorderTreeWalk: 4 3 1 2 5 7 6
InorderTreeWalk: 1 2 3 4 5 6 7
PostorderTreeWalk: 2 1 3 6 7 5 4
PreorderTreeWalk: 5 3 1 2 7 6
InorderTreeWalk: 1 2 3 5 6 7
PostorderTreeWalk: 2 1 3 6 7 5
PreorderTreeWalk: 6 3 1 2 7
InorderTreeWalk: 1 2 3 6 7
PostorderTreeWalk: 2 1 3 7 6
PreorderTreeWalk: 6 3 1 2
InorderTreeWalk: 1 2 3 6
PostorderTreeWalk: 2 1 3 6
PreorderTreeWalk: 3 1 2
InorderTreeWalk: 1 2 3
PostorderTreeWalk: 2 1 3
PreorderTreeWalk: 1 2
InorderTreeWalk: 1 2
PostorderTreeWalk: 2 1
PreorderTreeWalk: 2
InorderTreeWalk: 2
PostorderTreeWalk: 2
E:\GitHub\IntroductionToAlgorithms\C++\build\Debug\IntroductionToAlgorithms.exe (进程 4004)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .