二叉搜索树是一个可以动态管理集合的数据结构,相比于链表它可以更加有效地添加、搜索和删除数据。
二叉搜索树的各个结点都会有它的键值,且规定任一个相对的左子树的键值小于它的根结点的键值,而右子树的键值大于根结点的键值。
对于二叉搜索树,它的基本作用有插入、查找、删除。
插入:
插入过程的思想为:设当前的结点为x,要插入的结点为z,从根开始寻找插入的位置。若z的键值小于x,则将x的左儿子当作下一个x,反之,x的右儿子为下一个x,在此过程中,用y来存放访问的前一个结点,作为z的父结点候补。直到x为NULL,就找到了z的位置。而此时的y即为z的父结点。若y为NULL,说明插入前为空树,z为根结点。若插入前不为空,那么插入的结点z将根据键值大小成为y的左儿子或者右儿子。
#include <bits/stdc++.h>
using namespace std;
struct Node
{
int key;
Node *left,*right,*parent;
};
Node *root,*NIL;
void insert(int k)
{
Node *x=root;
Node *y=NIL;
Node *z;
z=(Node*)malloc(sizeof(Node));
z->key=k;
z->left=NIL;
z->right=NIL;
while(x!=NIL)
{
y=x;
if(x->key<z->key) x=x->right;
else x=x->left;
}
z->parent=y;
if(y==NIL) root=z;
else
{
if(z->key<y->key) y->left=z;
else y->right=z;
}
}
搜索:
利用二叉搜索树的性质,从上至下搜索,如果小于当前结点键值则找当前结点的左儿子,如果大于则找当前结点的右儿子。
#include <bits/stdc++.h>
using namespace std;
struct Node
{
int key;
Node *left,*right,*parent;
};
Node *root,*NUL;
Node * find(Node *u,int x)
{
while(u!=NUL&&u->key!=x)
{
if(x<u->key) u=u->left;
else u=u->right;
}
return u;
}
删除:
删除操作会比插入和搜索复杂一些,对于要删除的结点z,要考虑三种情况:
(1)z没有结点,删除z的父结点的子结点z,即它自己
(2)z有一个结点x,将z的父结点的子结点改为x,也将x的父结点改为z的父结点,然后将z删去
(3)z有两个结点,将z的后一个结点y(以中序排列为准)的键值复制到z,然后删除y
在(3)中,寻找z的后一个结点,当z有右结点时,右子树中键值最小的结点就为z的后一个结点。不存在右结点时,就向上寻找第一个为左子结点的身份出现的父结点。如果二叉搜索树中不存在x的后一个结点则返回NULL。
#include <bits/stdc++.h>
using namespace std;
struct Node
{
int key;
Node *left,*right,*parent;
};
Node *root,*NUL;
Node * getMinn(Node *u)
{
while(u->left!=NUL)
{
u=u->left;
}
return u;
}
Node * find(Node *u,int x)
{
while(u!=NUL&&u->key!=x)
{
if(x<u->key) u=u->left;
else u=u->right;
}
return u;
}
Node * getSuccessor(Node *u)
{
if(u->right!=NUL)
{
return getMinn(u->right);
}
Node *y=u->parent;
while(y!=NUL&&u==y->right)
{
u=y;
y=y->parent;
}
return y;
}
void treeDelete(Node *z)
{
Node *y;
Node *x;
if(z->left==NUL||z->right==NUL)
{
y=z;
}
else y=getSuccessor(z);
if(y->left!=NUL) x=y->left;
else x=y->right;
if(x!=NUL) x->parent=y->parent;
if(y->parent==NUL) root=x;
else
{
if(y->parent->left==y)
y->parent->left=x;
else y->parent->right=x;
}
if(y!=z) z->key=y->key;
free(y);
}