一、二分查找(折半查找)
在介绍二叉查找树之前,我们先来介绍一下二分查找。二分查找又称为折半查找,仅适用于有序顺序表。其基本思想是:首先将给定值K与表中中间位置的关键字比较,若相等,则查找成功,返回该元素的下标;若不等,则所查找的元素只能在中间数据以外前半部分或后半部分。然后在缩小的区间中继续进行同样的查找,如此重复直到找到为止,如果查找区间缩小到只有一个元素,其关键字仍不等于k,则查找失败。其算法实现如下:
int BinSearch(int data[],const int x,int beg,int last)
{
int mid; //中间位置
if (beg>last)
{
return-1;
}
while(beg<=last)
{
mid=(beg+last)/2;
if (x==data[mid] )
{
return mid; //查找成功
}
else if (data[mid]<x)
{
beg=mid+1; //向后半部分查找
}
else if (data[mid]>x)
{
last=mid-1; //向前半部分查找
}
}
return -1;
}
//递归法
int IterBinSearch(int data[],const int x,int beg,int last)
{
int mid = -1;
mid=(beg+last)/2;
if (x == data[mid])
{
return mid;
}
else if (x<data[mid])
{
return IterBinSearch(data,x,beg,mid-1);
}
else if (x>data[mid])
{
return IterBinSearch(data,x,mid+1,last);
}
return -1;
}
二、二叉查找树的基本操作
1、定义
二叉查找树中关键字的定义总是满足二叉查找树性质的方式来存储:设x是二叉查找树中的一个结点。如果y是x左子树中的一个结点,那么y.key<=x.key。如果y是x右子树中的一个结点,那么y.key>=x.key。
二叉查找树的基本操作包括SEARCH、MINIMUM、MAXMUM、INSERT、DELETE等基本操作,其算法的时间复杂度一般都为O(logN),下面将一一予以介绍。
2、查找二叉查找树T中具有关键字x的结点的指针
TNode Find(ElementType x, SearchTree T)
{
if(T==NULL)
return -1;
if(x<T->Element)
return Find(x,T->left);
else if (x>T>Elemrnt)
return Find(x,T->right);
else
return T;
}
3、二叉查找树的FindMin的递归实现
TNode FindMin(SearchTree T)
{
if(T==NULL)
return -1;
else if(T->left==NULL)
return T;
else
return FindMin(T->left);
}
4、二叉查找树的FindMax的非递归实现
TNode FindMax(SearchTree T)
{
if(T!=NULL)
while(T->right!=NULL)
T=T->right;
return T;
}
5、二叉查找树的插入算法
TNode Insert(ElementType x,SearchTree T)
{
if (T==NULL) //如果为空树则建立树
{
T=malloc(sizeof(struct TNode));
if(T==NULL)
cout<<"Out of space!";
else
{
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); //根结点起向右搜索的过程
else
; //如果已经在,则无需任何操作
return T;
}
6、二叉查找树的删除算法
TNode Delete(ElementType x,SearchTree T)
{
TNode temp;
if(T==NULL)
cout<<"Element not found!";
else if(x<T->Element)
T->left=Delete(x,T->left); //向左查找
else if(x>T->Element)
T->right=Delete(x,T->right); //向右查找
else if(T->left && T->right) //找到元素并且它既有左孩子又有右孩子
{
temp=FindMin(T->right);
T->Element=temp->Element;
T->right=Delete(T->Element,T->right); //用右子树的最小数据代替该结点的数据并递归地删除那个结点
}
else //一个孩子结点或者是叶结点
{
temp=T;
if(T->left==NULL)
T=T->right;
else if(T->right==NULL)
T=T->left;
free(temp);
}
return T;
}