二叉搜索树相比于其他数据结构的优势在于查找、插入的时间复杂度较低,插入的时间复杂度为O(log n), 二叉搜索树是基础性的数据结构,用于构建更为抽象的数据结构,如集合、multiset、关联数组等。
二叉搜索树的查找、插入、删除的时间复杂度等于树高的期望O(log n),最差时间复杂度为O(n)(数组有序,树退化成线性表)。
二叉搜索数的操作中的难点是二叉搜索树中特定节点的删除。在二叉搜索树中删除一个节点,分三种情况讨论:
1. 若*p结点为叶子结点,即PL(左子树)和PR(右子树)均为空树。由于删去叶子结点不破坏整棵树的结构,则只需修改其双亲结点的指针即可。
2. 若*p结点只有左子树PL或右子树PR,此时只要令PL或PR直接成为其双亲结点*f的左子树(当*p是左子树)或右子树(当*p是右子树)即可,作此修改也不破坏二叉查找树的 特性。即p=p->left 或者 p=p->right。
3.若*p的左右节点都不为空。在删除*p之后,为保持其他元素之间的相对位置不变,可按中序遍历保持有序进行调整 ,可以有两种做法:
方法(1):令*p的左子树直接为其父节点*f的左子树或右子树(依*p是*f的左孩子还是右孩子而定),若设*s为待删节点*p左子树上的最右下的节点(值最大的节点),则还需将*p的右子树变为*s的右子树。
方法(2):设*s为待删节点*p左子树上的最右下的节点(值最大的节点),将节点*s的右子树接到其父节点上,作为其父节点的右子树,而后用节点*s的值替换掉待删节点*p的节点的值。
方法(1)说明代码:
void delete_node1(ptrnode &p)//注意参数必须为引用
{
ptrnode q,s;
if(!p->left && !p->right)//when p is a leaf node;
{
q=p;
p=NULL;
free(q);
}
else if(!p->left)//when p only have rightchild node;
{
q=p;
p=p->right;
free(q);
}
else if(!p->right)//when p only have leftchild node;
{
q=p;
p=p->left;
free(q);
}
else //when p have both leftchild and right child node;
{
s=p->left;
while(s->right!=NULL)
{
s=s->right;
}
s->right=p->right;
q=p;
p=p->left;
free(q);
}
}
方法(2)说明代码:
void delete_node2(ptrnode &p) //注意参数必须为引用
{
ptrnode q,s;
if(!p->left && !p->right)//when p is a leaf node;
{
q=p;
p=NULL;
free(q);
}
else if(!p->left)//when p only have rightchild node;
{
q=p;
p=p->right;
free(q);
}
else if(!p->right)//when p only have leftchild node;
{
q=p;
p=p->left;
free(q);
}
else //when p have both leftchild and right child node;
{
s=p->left;
while(s->right!=NULL)
{
q=s;
s=s->right;
}
p->element=s->element;
if(p!=q)
q->right=s->left;
else
q->left=s->left;
free(s);
}
}
注意:这里函数中的参数必须为引用,弄清楚原因
下面是二叉搜索树的完整代码,插入,删除,查找,遍历以及测试用例:
#include<iostream>
using namespace std;
typedef struct Node
{
int element;
struct Node * left;
struct Node * right;
}TreeNode,*BSTree,*ptrnode;
ptrnode Insert(int x,BSTree &T)
{
if(NULL==T)
{
T=(ptrnode)malloc(sizeof(TreeNode));
if(T==NULL)
{
cout<<"out of space!"<<endl;
exit(0);
}
T->element=x;
T->left=T->right=NULL;
}
else if(x<T->element)
{
T->left=Insert(x,T->left);
}
else if(x>T->element)
{
T->right=Insert(x,T->right);
}
return T;
}
ptrnode Find(int x,BSTree &T)
{
if(NULL==T)
return NULL;
if(x<T->element)
return Find(x,T->left);
else if(x>T->element)
return Find(x,T->right);
else
return T;
}
ptrnode FindMin(int x,BSTree &T)
{
if(NULL==T)
return NULL;
if(NULL==T->left)
return T;
else
return FindMin(x,T->left);
}
ptrnode FindMax(int x,BSTree &T)
{
if(NULL==T)
return NULL;
if(NULL==T->right)
return T;
else
return FindMax(x,T->right);
}
void delete_node1(ptrnode &p)//注意参数必须为引用
{
ptrnode q,s;
if(!p->left && !p->right)//when p is a leaf node;
{
q=p;
p=NULL;
free(q);
}
else if(!p->left)//when p only have rightchild node;
{
q=p;
p=p->right;
free(q);
}
else if(!p->right)//when p only have leftchild node;
{
q=p;
p=p->left;
free(q);
}
else //when p have both leftchild and right child node;
{
s=p->left;
while(s->right!=NULL)
{
s=s->right;
}
s->right=p->right;
q=p;
p=p->left;
free(q);
}
}
void delete_node2(ptrnode &p) //注意参数必须为引用
{
ptrnode q,s;
if(!p->left && !p->right)//when p is a leaf node;
{
q=p;
p=NULL;
free(q);
}
else if(!p->left)//when p only have rightchild node;
{
q=p;
p=p->right;
free(q);
}
else if(!p->right)//when p only have leftchild node;
{
q=p;
p=p->left;
free(q);
}
else //when p have both leftchild and right child node;
{
s=p->left;
while(s->right!=NULL)
{
q=s;
s=s->right;
}
p->element=s->element;
if(p!=q)
q->right=s->left;
else
q->left=s->left;
free(s);
}
}
bool delete_BSTree(int x,BSTree &T)//参数必须为引用
{
if(NULL==T)
return false;
else
{
if(x<T->element)
return delete_BSTree(x,T->left);
else if(x>T->element)
return delete_BSTree(x,T->right);
else
{
//delete_node1(T);
delete_node1(T);
return true;
}
}
}
void MakeEmpty(BSTree &T)//destroy the BSTree
{
if(NULL==T)
return ;
else
{
if(T->left!=NULL)
MakeEmpty(T->left);
if(T->right!=NULL)
MakeEmpty(T->right);
free(T);
}
}
void Preorder_traverse(BSTree &T)
{
if(T==NULL)
return;
else
{
cout<<T->element<<" ";
Preorder_traverse(T->right);
Preorder_traverse(T->left);
}
}
void Inorder_traverse(BSTree &T)
{
if(T==NULL)
return;
else
{
Inorder_traverse(T->left);
cout<<T->element<<" ";
Inorder_traverse(T->right);
}
}
void Postorder_traverse(BSTree &T)
{
if(T==NULL)
return;
else
{
Postorder_traverse(T->left);
Postorder_traverse(T->right);
cout<<T->element<<" ";
}
}
//-----------------------------------------------------测试用例 test case
void Test1()// p only have a child node(left child)
{
BSTree T=NULL;
T=Insert(6,T);
T=Insert(2,T);
T=Insert(8,T);
T=Insert(1,T);
T=Insert(4,T);
T=Insert(3,T);
cout<<"the inorder_traverse is "<<endl;
Inorder_traverse(T);
cout<<endl;
delete_BSTree(4,T);
cout<<"after the delete,the inorder_traverse is "<<endl;
Inorder_traverse(T);
cout<<endl;
MakeEmpty(T);
}
void test2()//p have no child
{
BSTree T=NULL;
T=Insert(6,T);
T=Insert(2,T);
T=Insert(8,T);
T=Insert(1,T);
T=Insert(4,T);
T=Insert(3,T);
cout<<"the inorder_traverse is "<<endl;
Inorder_traverse(T);
cout<<endl;
delete_BSTree(3,T);//the node 3 is a leaf node
cout<<"after the delete,the inorder_traverse is "<<endl;
Inorder_traverse(T);
cout<<endl;
MakeEmpty(T);
}
void test3()
{
BSTree T=NULL;
T=Insert(6,T);
T=Insert(2,T);
T=Insert(8,T);
T=Insert(1,T);
T=Insert(5,T);
T=Insert(3,T);
T=Insert(4,T);
cout<<"the inorder_traverse is "<<endl;
Inorder_traverse(T);
cout<<endl;
delete_BSTree(2,T);
cout<<"after the delete,the inorder_traverse is "<<endl;
Inorder_traverse(T);
cout<<endl;
cout<<"after the delete,the preorder_traverse is "<<endl;
Preorder_traverse(T);
cout<<endl;
cout<<"after the delete,the postorder_traverse is "<<endl;
Postorder_traverse(T);
cout<<endl;
}
int main(void)
{
cout<<"----------------------------------------test case1"<<endl;
Test1();
cout<<"----------------------------------------test case2"<<endl;
test2();
cout<<"----------------------------------------test case3"<<endl;
test3();
return 0;
}
运行结果: