1.概念:
二叉查找树也叫二叉搜索树,是一棵空树或者是具有一下性质的一颗二叉树
a.每个节点都有一个作为搜索依据的关键码(key),而且所有的关键码的取值都互不相同。
b.每个左子树(如果存在)所有节点的关键码都小于根节点的关键码。
c.每个右子树(如果存在)所有节点的关键码都大于根节点的关键码。
d.每个左子树和右子树也均为二叉搜索树。
需要说明的是,关键码事实上是节点所保存元素中的某个域的值,它能够唯一的表示这个结点,因此,如果对一颗二叉搜索树进行中序遍历,就可以按照从小到大的顺序将各个结点的关键排列起来,因此二叉搜索树也被称为二叉排序树。
2.二叉搜索树相关的算法:
a.搜索算法:
在二叉搜索树上进行搜索,过程是从一个根节点开始,沿着某一个分支逐层向下进行比较判别的过程,这个过程可以是一个递归的过程,也可以是一个迭代的过程。因为通常使用递归的方法来定义二叉树类,因此搜索算法通常也使用递归的思想来编写。主要过程如下:
假设想要在二叉搜索树中搜索关键码为x的元素,搜索过程从根节点开始,如果根结点为nullptr(空指针),则直接返回搜索失败,否则用给定的值x与根结点的关键码相比较,如果给定的值等于根结点的关键码中的值,则返回搜索成功的信息,并提交搜索到的结点地址。如果给定值小于根结点的关键码,则继续递归搜索根结点的左子树,窦泽,进行递归搜索根结点的右子树。
b.插入算法:
向二叉搜索树中插入一个元素,必须先检查这个元素在已有的树中是否已经存在。所以 在进行插入之前,可以先使用搜索算法在树中检查准备要插入的元素是否存在。如果返回搜索成功的信息,说明在这棵二叉搜索树中已有这个元素,就不再进行插入操作。否则,说明在树中没有要插入的这个元素。再把新元素添加到搜索操作停止的地方。在将要插入的元素与搜索操作返回的地址的关键码相比较。如果小于,则插入为左子树,否则成为右子树。
在插入过程中需要注意,每次的结点的插入,都要从根结点出发先搜索插入的位置,然后把新结点作为叶结点插入,这样不需要移动结点,只需要修改某个已有树中结点的空指针即可。
c.二叉搜索树的删除
在二叉搜索树中删除一个结点时,必须将因删除结点而断开的二叉链表重新连接起来,同时又要确保二叉搜索树的性质不丢失。此外,为了保证在删除结点后树的搜索性能不至于降低,还需要防止重新连接后输的高度不能增加。因此,删除算法需要分为几种情况进行讨论。
(1).如果想要删除叶结点,只需将父结点指向它的指针进行清零操作即可,在释放掉这个结点即可。
(2).如果被删除的结点右子树为空,则可以用它的左子女结点代替它的位置,再释放掉这个结点;若被删除结点左子树为空,则可以用它的右子女结点代替它的位置,再释放掉这个结点即可。
(3)如果被删除结点的左右子树都不为空,则可以在它的右子树下寻找中序下的第一个结点(关键码最小),用它的值填补到被删除的结点中,再来处理这个结点的删除问题。
同样的,这也是一个递归处理的过程。之后进行递归删除即可。
相关实现程序如下
二叉搜索树的头文件:
/
// BST.h
// BinarySearchTree
//
// Created by 大幕 on 2017/3/2.
// Copyright © 2017年 Damu. All rights reserved.
//
// 构建一颗二叉查找树并进行使用
// 特点,每一个元素有一个键值,左子树比根节点小,右子树比根节点大,且左右子树都是二叉查找树
#ifndef BST_h
#define BST_h
#include <iostream>
enum Boolean { FALSE, TRUE }; //定义自己的布尔类型
//使用C++的模板类来设计二叉查找树
template <class Type>
class Element
{
public:
Type key;
//可以很容易的添加更多的数据
};
template<class Type> class BST; //声明类
template <class Type>
class BstNode //二叉查找树的结点类
{
friend class BST<Type>; //定义为友元类,方便操作BstNode的私有成员
public:
Element<Type> data;
BstNode * LeftChild;
BstNode * RightChild;
void display(int i);
};
template <class Type>
class BST
{
public:
BST(BstNode<Type> *init = 0)
{
root = init;
}
Boolean Insert(const Element<Type>& x); //插入结点操作
Boolean Remove(BstNode<Type> * ptr, const Element<Type>& x); //删除以ptr为根结点,关键码为x的结点
Boolean Remove(const Element<Type>& x); //配合上一个函数实现删除操作
BstNode<Type>* Search(const Element<Type>& x); //使用递归的方法进行查找
BstNode<Type>* Search(BstNode<Type> *, const Element<Type> &); //重载函数进行查找
BstNode<Type>* IterSearch(const Element<Type>&); //使用迭代进行查找
void display()
{
std::cout << '\n';
if (root)
root->display(1);
else
std::cout << "这是一颗空树\n";
}
private:
BstNode<Type> *root;
};
template <class Type>
void BstNode<Type>::display(int i)
{
//用来显示当前节点的数据以及它所有的左子树和右子树的数据,利用递归的方法
std::cout << "Position: " << i << ": data.key = " << data.key << '\n'; //先显示位置,再显示数据
if (LeftChild)
LeftChild->display(2 * i); //递归左子树
if (RightChild)
RightChild->display(2 * i + 1); //递归右子树
}
template <class Type>
Boolean BST<Type>::Insert(const Element<Type> &x)
{
BstNode<Type> *p = root;
BstNode<Type> *q = 0; //q指向p的父节点
//insert之前需要先进行查找,找到合适的位置进行插入
while (p)
{
q = p; //在每次改变之前使用q将p进行保留下来
if (x.key == p->data.key)
return FALSE; //发生重复,插入失败
if (x.key < p->data.key)
p = p->LeftChild;
else
p = p->RightChild;
}
//循环结束后,找到了位置q
p = new BstNode<Type>;
p->LeftChild = nullptr;
p->RightChild = nullptr;
p->data = x;
if (!root)
root = p;
else if (x.key < q->data.key)
q->LeftChild = p;
else
q->RightChild = p;
return TRUE; //表示插入成功
}
//删除以ptr为根结点,关键码为x的结点
template<class Type>
Boolean BST<Type>::Remove(BstNode<Type> * ptr, const Element<Type>& x)
{
BstNode<Type> *temp = nullptr;
ptr = root;
if (ptr != nullptr)
{
if (x.key < ptr->data.key)
Remove(ptr->LeftChild, x); //在左子树中执行删除
else if (x.key > ptr->data.key)
Remove(ptr->RightChild, x); //在右子树中执行删除
else if (ptr->LeftChild != nullptr && ptr->RightChild != nullptr)
{
//ptr指到了关键码为x的结点,而且这个结点有两个子女
temp = ptr->RightChild; //找到右子树搜寻中序下的第一个结点
while (temp->LeftChild != nullptr)
temp = temp->LeftChild;
ptr->data.key = temp->data.key; //使用temp中数据代替此时ptr结点中的数据
Remove(ptr->RightChild, ptr->data); //递归删除右子树中的temp结点
}
else
{
//ptr也指到了关键码为x的结点,但是它只有1个或0个子女
temp = ptr;
if (ptr->LeftChild == nullptr)
ptr = ptr->RightChild;
else
ptr = ptr->LeftChild;
delete temp;
return TRUE;
}
}
return FALSE;
}
//删除函数
template <class Type>
Boolean BST<Type>::Remove(const Element<Type> &x)
{
return Remove(root, x);
}
//搜索函数
template <class Type>
BstNode<Type> *BST<Type>::Search(const Element<Type> &x)
{
return Search(root, x);
}
template<class Type>
BstNode<Type> * BST<Type>::Search(BstNode<Type> *b, const Element<Type>& x)
{
//从节点b开始找数值为x的结点
if (!b)
return 0;
if (x.key == b->data.key)
return b;
if (x.key < b->data.key)
return Search(b->LeftChild, x);
return Search(b->RightChild, x);
}
//迭代的查找方法
template<class Type>
BstNode<Type>* BST<Type>::IterSearch(const Element<Type> &x)
{
for (BstNode<Type> *t = root; t;)
{
if (x.key == t->data.key)
return t;
if (x.key < t->data.key)
t = t->LeftChild;
else
t = t->RightChild;
}
return 0;
}
#endif /* BST_h */