属性:1.每一个节点都带有唯一一个关键字
2.左节点比父节点小,右节点比父节点大,左节点是左子树上所有的节点,右节点是右子树上所有的节点
3.任何一个子树依旧是一个二叉搜索树
4.中序遍历打印的值是有序排列的
我们来具体实现一个二叉搜索树,下面是代码
#include<iostream>
#include<stdlib.h>
#include<string>
using namespace std;
struct bstTree {
int val;
bstTree* left;
bstTree* right;
};
//定义往二叉搜索树BST插入节点的函数
void insert(bstTree** T, int data)//为什么要传二级指针呢?因为我们要改变指针中存放的地址,改变值要传二级指针
{
//*T指向NULL
if (*T == NULL)
{
bstTree* node = new bstTree();//申请一个新的节点
node->val = data;
node->left = NULL;
node->right = NULL;
*T = node;
}
else {
if ((*T)->val>data)
{
//要插入的节点小于当前指针指向的节点
//要插入的节点要放到当前节点的左子树
insert(&((*T)->left), data);
}
else {
//要插入的节点大于当前指针指向的节点
//要插入的节点要放到当前节点的右子树
insert(&((*T)->right), data);
}
}
}
//中序遍历BST树
void InorderTree(bstTree* T)
{
if (T == NULL)
{
return;
}
else {
InorderTree(T->left);
cout << T->val << " ";
InorderTree(T->right);
}
}
int main() {
//定义空树
bstTree* T = NULL;
int data;
//输入10个数字
for (int i = 0; i < 10; i++)
{
cout << "请输入数字: ";
cin >> data;
insert(&T, data);
}
cout << endl;
InorderTree(T);
cout << endl;
system("pause");
return 0;
}
查找操作:在二叉搜索树来找到对应的节点
//查找二叉树中的节点
//递归
bstTree* search1(bstTree* T, int val)
{
//val 是我们要找的值
if (T == NULL)
{
return NULL;
}
else if (T->val > val)
{
return search1(T->left, val);
}
else if (T->val < val)
{
return search1(T->right, val);
}
else {
return T;
}
return NULL;
}
//通过迭代的方式来找到val值
bstTree* search2(bstTree* T, int val)
{
bstTree* cur = T;
while (cur != NULL)
{
if (cur->val > val)
{
cur = cur->left;
}
else if (cur->val < val)
{
cur = cur->right;
}
else if (cur->val == val)
{
return cur;
}
}
return NULL;
}
删除操作:
我们在二叉搜索树中进行删除操作,一共有三种情况
(1)第一种情况:删除的节点既没有左子树,又没有右子树,例如删除下面二叉搜索树中的2,4,13等节点,我们直接返回NULL就行
(2)第二种情况:删除的节点仅仅只有一个子树(可以是左子树也可以是右子树),我们直接将该节点删除即可,返回它的左子树和右子树就行了,就像删除上面树中的7节点
(3)第三种情况:删除节点既有左子树又有右子树,我们又两种处理方法,第一种:我们可以将右节点接到左子树的最右的叶节点上,第二种:我们可以将左节点街道右子树的最左的叶节点上
我们看看图:下面是我们将6节点删除,将右子树的节点接到了左子树最右边的节点上
那我们将左子树的节点接到右子树的最左节点上
我们看看代码
//定义删除二叉搜索树中的节点
bstTree* deleteNode(bstTree* T, int val)
{
//如果是空树,返回NULL
if (T == NULL)
return NULL;
if (T->val > val) {
//要找的节点小于当前节点,那就递归删除左子树上 的节点
T->left = deleteNode(T->left, val);
return T;
}
else if (T->val < val) {
//要找的节点大于当前节点,那就递归删除右子树上的节点
T->right = deleteNode(T->right, val);
return T;
}
else if (T->val == val) {
//这时候要删除的节点有下面三种情况
//1.要删除的节点没有左右子树
if (T->left == NULL && T->right == NULL) {
bstTree* Node = T;
delete T;//因为申请的内存都是在堆区的,所以要用delete来释放掉内存
Node = NULL;
return Node;
}
//2.要删除的节点有左孩子,但是没有右孩子,就让左孩子来代替这个节点
else if (T->right == NULL && T->left != NULL) {
bstTree* Node = T->left;
delete T;
return Node;
}
//要删除的节点有右孩子,但没有左孩子,那就让右孩子来代替这个节点
else if (T->right != NULL && T->left == NULL) {
bstTree* Node = T->right;
delete T;
return Node;
}
//3.要删除的节点有左孩子又有右孩子,那就将右孩子节点加到左孩子中最大的节点的右孩子上
else if (T->right != NULL && T->left != NULL) {
//找到左节点中最大的节点
bstTree* cur = T->left;
while (cur->right != NULL)
{
cur = cur->left;
}
//将T的右子树加到左子树上的最大节点上
cur->right = T->right;
bstTree* Node = T->left;
delete T;
return Node;
}
}
//没有找到要删除的节点
return T;
}