1.二叉搜索树(二叉排序树)的定义
二叉搜索树或者是空树,或者具有以下性质的二叉树:
① 若左子树为空,则左子树上所有结点的关键字值均小于它的根节点的关键字值。
② 若右子树为空,则右子树上所有结点的关键字值均大于它的根节点的关键字值。
③左右子树本身又是一颗二叉搜索树。
2.二叉搜索树的查找
查找思路为:若待查找数据元素的关键字值等于二叉搜索树根节点的关键字值,则查找成功;若待查找数据元素的关键字值大于二叉搜索树根节点的关键字值,则在根节点的右子树中继续查找;若待查找数据元素的关键字值小于二叉搜索树根节点的关键字值,则在根节点的左子树中继续查找;
3.二叉搜索树的插入
插入的思路为:若二叉排序树为空,则将新节点作为根插入;若二叉搜索树非空,则将新节点的关键字值与根节点的关键字值相比较,若等于根节点关键字值,则不插入;若大于根节点的关键字值,则插入到二叉搜索树的右子树中;若小于根节点的关键字值,则插入到二叉搜索树的左子树中。
4.二叉搜索树的删除
删除思路为:先查找,如果删除的元素不存在,则直接返回;若存在则分其它情况
①叶子结点
a.只有根节点,则直接删除根节点并置空。
b.叶子结点是左子树和叶子结点是右子树
②只有左孩子
③只有右孩子
④左右孩子都有
5.模拟实现
#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
typedef int ElemType;
template<class T>
struct BinaryTreeNode
{
T key; //关键字
BinaryTreeNode<T> *left; //左孩子
BinaryTreeNode<T> *right; //右孩子
BinaryTreeNode<T> *parent; //父节点
BinaryTreeNode(const T&x)
:key(x),
left(NULL),
right(NULL),
parent(NULL)
{}
};
template<class T>
struct BinaryFindTree
{
typedef BinaryTreeNode<T> Node;
public:
BinaryFindTree() //无参构造函数
:_root(NULL)
{}
BinaryFindTree(T* a, size_t n) //构造函数
{
size_t index = 0;
CreateTree(a, n, index);
}
void PreOrderHelp() //前序遍历
{
_PreOrderHelp(_root);
cout << endl;
}
void _PreOrderHelp(const Node *root)const //前序遍历
{
if (root != NULL)
{
cout << root->key << " ";
_PreOrderHelp(root->left);
_PreOrderHelp(root->right);
}
}
void InOrderHelp() //中序遍历
{
_InOrderHelp(_root);
cout << endl;
}
void _InOrderHelp(const Node *root)const //中序遍历
{
if (root != NULL)
{
_InOrderHelp(root->left);
cout << root->key << " ";
_InOrderHelp(root->right);
}
}
void PostOrderHelp() //后序遍历
{
_PostOrderHelp(_root);
cout << endl;
}
void _PostOrderHelp(const Node* root)const //后序遍历
{
if (root != NULL)
{
_PostOrderHelp(root->left);
_PostOrderHelp(root->right);
cout << root->key << " ";
}
}
Node* Insert(Node *&root, const T& key) //插入
{
Node *newroot = new Node(key);
if (root == NULL) //空树
{
newroot->left = NULL;
newroot->right = NULL;
newroot->parent = root;
root = newroot;
_root = root;
}
Node* ccur = root;
Node* cur = root;
while (ccur != NULL)
{
if (ccur->key > key)
{
cur = ccur;
ccur = ccur->left;
}
else if (ccur->key < key)
{
cur = ccur;
ccur = ccur->right;
}
else
break;
}
if (cur->left == NULL && cur->key > key)//左孩子
{
cur->left = newroot;
newroot->left = NULL;
newroot->right = NULL;
newroot->parent = cur;
ccur = root;
}
if (cur->right == NULL && cur->key < key) //右孩子
{
cur->right = newroot;
newroot->left = NULL;
newroot->right = NULL;
newroot->parent = cur;
ccur = root;
}
return root;
}
Node* Search(Node* root, const T& key) //查找元素,找到返回关键字的结点指针,没找到返回NULL
{
if (root == NULL)
return root;
if (root->key > key) //查找左子树
return Search(root->left, key);
else if (root->key < key)
return Search(root->right, key);
}
Node* SearchMin(Node* root) //查找最小关键字,空树时返回NULL
{
if (root == NULL)
return root;
while (root->left != NULL)
root = root->left;
return root;
}
Node* SearchMax(Node* root) //查找最大关键字,空树时返回NULL
{
if (root == NULL)
return root;
while (root->right != NULL) //迭代
root = root->right;
return root;
}
Node* SearchPredecessor(Node* cur) //查找前驱
{
if (cur == NULL) //空
return cur;
if (cur->left != NULL) //若存在左孩子,前驱是其左子树中最大的
return SearchMax(cur->left);
Node* prev = cur->parent;
while (prev != NULL && cur == prev->left)
{
cur = prev;
prev = cur->parent;
}
return prev;
}
Node* SearchSuccessor(Node* cur)//查找后继
{
if (cur == NULL) //空
return cur;
if (cur->right != NULL) //若存在右孩子,后继是其右子树中最小的
return SearchMin(cur->right);
Node* prev = cur->parent;
while (prev != NULL && cur == prev->right)
{
cur = prev;
prev = cur->parent;
}
return prev;
}
int DeleteNode(Node *&root, const T& key)
{
Node* q;
Node* p = Search(root, key);//查找到要删除的结点
if (p == NULL)
return 0;
//一共有四种情况,该节点是叶子节点、只有左孩子、只有右孩子、左右孩子都有
//叶子结点
if (p->left == NULL && p->right == NULL)
{
if (p->parent == NULL) //只有根节点
{
free(p);
root = NULL;
}
else
{
//删除的结点是左孩子
if (p->parent->left == p)
p->parent->left = NULL;
else //右孩子
p->parent->right = NULL;
free(p);
}
}
//左孩子
else if (p->left != NULL && p->right == NULL)
{
p->left->parent = p->parent;
//如果删除是根结点
if (p->parent == NULL)
root = p->left;
//父节点的左孩子
else if (p->parent->left == p)
p->parent->left = p->left;
else
p->parent->right = p->left;
free(p);
}
//右孩子
else if (p->right != NULL && p->left == NULL)
{
p->right->parent = p->parent;
//如果删除是根结点
if (p->parent == NULL)
root = p->right;
//是父节点的左孩子
else if (p->parent->left == p)
p->parent->left = p->right;
else
p->parent->right = p->right;
free(p);
}
//左右孩子都有
//该结点的后继结点肯定无左子树
//删掉后继结点,后继结点的值代替该结点
else
{
//找到要删除结点的后继
q = SearchSuccessor(p);
ElemType temp = q->key; //暂存后继结点的值
//删除后继结点
DeleteNode(root, q->key);
p->key = temp;
}
return 1;
}
Node* CreateTree(T* a, size_t n, size_t& index) //创建子树
{
Node* root = _root = NULL;
while (index < n)
{
Insert(root, a[index]);
index++;
}
return root;
}
protected:
Node* _root;
};
void test()
{
typedef BinaryTreeNode<int> Node;
int Array[11] = { 15, 6, 18, 3, 7, 17, 20, 2, 4, 13, 9 };
//int Array[5] = { 5, 3, 6, 2 ,4};
BinaryFindTree<int> T2;
size_t index = 0;
Node* ret = T2.CreateTree(Array, sizeof(Array) / sizeof(Array[0]), index);
T2.InOrderHelp();
T2.PreOrderHelp();
T2.PostOrderHelp();
//cout << T2.Search(ret, 20) << endl;
//T2.Insert(ret, 1);
//cout << T2.SearchMin(ret) << endl;
//cout << T2.SearchMax(ret) << endl;
T2.DeleteNode(ret, 3);
T2.InOrderHelp();
}
int main()
{
test();
system("pause");
return 0;
}