二叉查找树的查找(查找某个值、查找最小元素、查找最大元素)、插入、删除操作的最坏时间都为O(h)。构造二叉查找树时采取随机算法,可以让二叉查找树的期望高度为O(lgn),则前面那些操作的最坏时间就可以为O(lgn)。非常高效的算法。
代码如下:
#include <iostream>
using namespace std;
struct TreeNode
{
int key;
TreeNode *p;
TreeNode *left;
TreeNode *right;
};
//中序遍历,实现从小到大输出序列
void InorderTreeWalk(TreeNode *root)
{
if(root!=NULL)
{
InorderTreeWalk(root->left);
cout<<root->key<<" ";
InorderTreeWalk(root->right);
}
}
//查询二叉查找树,在数中查找k,返回其指针(递归版)
TreeNode* TreeSearch(TreeNode *root,int k)
{
if(root!=NULL)
{
if(root->key==k)
{
return root;
}
else if(key<root->key)
{
TreeSearch(root->left,k);
}
else if(key>root->key)
{
TreeSearch(root->right,k);
}
}
else
{
return NULL;
}
}
//查询二叉查找树,在数中查找k,返回其指针(迭代版)
TreeNode* TreeSearch(TreeNode *root,int k)
{
while(root!=NULL&&root->key!=k)
{
if(root->key>k)
{
root=root->left;
}
else if(root->key<k)
{
root=root->right;
}
}
return root;
}
//返回指向最小值的指针
TreeNode* TreeMinimum(TreeNode *root)
{
if(root->left!=NULL)
{
TreeMinimum(TreeNode->left);
}
return root;
}
//返回指向最大值的指针
TreeNode* TreeMaxmum(TreeNode *root)
{
if(root->right!=NULL)
{
TreeMaxmum(root->right);
}
return root;
}
//返回x的后继的指针
TreeNode* TreeSuccessor(TreeNode *x)
{
if(x->right!=NULL)
{
return TreeMinimum(x->right);
}
//如果x没有右儿子,那么它的后继肯定是它的一个祖先。而且它肯定在它这个祖先的左枝上。而且这个祖先是符合条件的祖先中离他最近的那一个。
TreeNode *y=x->p;
while(y!=NULL && x==y->right)
{
x=y;
y=y->p;
}
return y;
}
//返回x的前驱的指针
TreeNode* TreePredecessor(TreeNode *x)
{
if(x->left!=NULL)
{
return TreeMaxmux(x->left);
}
//如果x没有左儿子,那么它的前驱肯定是他的一个祖先。而且它肯定在它这个祖先的右枝上。而且这个祖先是符合条件的祖先中离它最近的那一个。
y=x->p;
while(y!=NULL && x==y->right)
{
x=y;
y=y->p;
}
return y;
}
//插入操作:把一个新值v插入到二叉查找树中。(递归版)
void TreeInsert(TreeNode *root,int v,TreeNode *y)//让y指向v的父节点
{
if(root==NULL)
{
root=new TreeNode;
if(root==NULL)
{
return;
}
root->key=v;
root->p=y;
root->left=NULL;
root->right=NULL;
if(y!=NULL)
{
if(y->key<v)
{
y->right=root;
}
else
{
y->left=root;
}
}
}
else
{
y=root;
if(root->key > v)
{
TreeInsert(root->left,v,y);
}
else
{
TreeInsert(root->right,v,y);
}
}
}
//插入操作:把一个新值v插入到二叉查找树中。( 迭代版)
void TreeInsert(TreeNode *root,int v)
{
TreeNode *y=root;
while(root!=NULL)
{
y=root;
if(root->key > k)
{
root=root->left;
}
else
{
root=root->right;
}
}
root=new TreeNode;
if(root==NULL)
{
return;
}
root->key=k;
root->p=y;
root->left=NULL;
root->right=NULL;
if(y!=NULL)
{
if(y->key<v)
{
y->right=root;
}
else
{
y->left=root;
}
}
}
//删除某个值v所在的节点
void TreeDelete(TreeNode *root,int v)
{
//先找到v所在的节点
TreeNode *z=TreeSearch(root,v);
if(z==NULL)
{
return;
}
TreeNode *y=NULL;//令y指向被删除节点。则y要么是z(z只有一个子女或无子女),要么是z的后继节点(z有两个子女)。
if(z->left==NULL || z->right==NULL)
{
y=z;
}
else
{
y=TreeSuccessor(z);
if(y==NULL)//z无后继结点
{
y=z;
}
}
TreeNode *x=NULL;//令x指向y的非空子女,如果y无子女则x为NULL
if(y->left!=NULL)
{
x=y->left;
}
else
{
x=y->right;
}
//修改y和x相关的指针
if(x!=NULL)
{//若x不为空,修改x的父节点为y的父节点
x->p=y->p;
}
if(y->p!=NULL)
{//如果y的父节点不为空,则修改y的父节点的子女,将x放到y所在的位置
if(y==(y->p)->left)
{
(y->p)->left=x;
}
else
{
(y->p)->left=x;
}
}
else
{//如果y的父节点为空,则y为树根。此时应将x置为树根。
root=x;
}
if(y!=z)//如果要删除的是z的后继,则将后继结点数据复制到z
{
z->key=y->key;
}
delete y;
}
//随机化算法:本地操作,a0与(a0,...,an-1)交换,。。。。。
void Random(int *a,int n)
{
srand((unsigned int)time(NULL));
for(int i=0;i<n;i++)
{
int j=rand()%(n-i)+i;
int temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
//随机构造二叉查找树(之所以引入随机化,是为了让二叉查找树的期望高度为O(lgn)
void RandomCreateTree(TreeNode *root,int *a,int n)
{
//先用随机化算法将数组进行随机化
Random(a,n);
root=NULL;
for(int i=0;i<n;i++)
{
TreeInsert(root,a[i]);
}
}
void Output(int *a,int n)
{
for(int i=0;i<n;i++)
{
printf("%d ",a[i]);
}
cout<<endl;
}