1. 顺序查找:
对线性表顺序扫描进行查找,顾名思义,无需多言。其时间代价为O(n).
2. 二分查找:
要求线性表中元素是有序的。其时间代价为O(lgn).
缺点:不能用链表作存储结构,因此,当表的插入或删除操作频繁时,为维护表的有序性,需要移动表中很多记录。这种由移动记录引起的额外时间开销,就会抵消二分查找的优点。
int BinSearch(LineList R[],int n,KeyType k)
{
int i,low=0,high=n-1,mid; //注意这里有些是从1到n,要谨慎处理
int find=0; //=0表示未找到,=1表示已找到
while(low<=high && !find){
mid=(low+high)/2;
if(k < R[mid].key)
high=mid-1;
else if(k > R[mid].key)
low=mid+1;
else{
i=mid;find=1;
}
}
if(find==0)
return -1;
else
return i;
}
3. 二叉查找树:
弥补二分查找关于动态查找的缺点,用二叉树作为表的组织形式。时间代价为O(lgn)它或者是一棵空树,或者是一棵具有以下特点的非空二叉树:
(1)若左子树非空,则左子树所有节点关键字均小于根结点的关键字;
(2)若右子树非空,则右子树所有节点关键字均大于(大于等于)根结点关键字;
(3)左右子树本身又各是一棵二叉查找树。
其链式存储结构节点类型为:
typedef struct tnode
{
KeyType key;
ElemType data;
struct tnode *lchild,*rchild;
}BSTNode;
基本运算如下所示:
//查找
BSTNode *BSTSearch(BSTNode *bt,KeyType k)
{
BSTNode *p=bt;
while(p!=NULL && p->key!=k){
if(k < p->key)
p=p->lchild;
else
p=p->rchild
}
return p;
}
//插入
int BSTInsert(BSTNode *&bt,KeyType k)
{
BSTNode *f,*p=bt;
while(p!=NULL){
if(p->key==k) return 0;
f=p; //f指向*p节点的双亲节点
if(p->key > k)
p=p->lchild;
else
p=p->rchild;
}
p=(BSTNode *)malloc(sizeof(BSTNode));
p->key=k;
p->lchild=p->rchild=NULL;
if(bt==NULL)
bt=p;
else if(k < f->key)
f->lchild=p;
else
f->rchild=p;
return 1;
}
//创建二叉查找树
void CreateBST(BSTNode *&bt,KeyType str[],int n)
{
bt=NULL;
int i=0;
while(i<n){
BSTInsert(bt,str[i]);
i++;
}
}
//删除
int BSTDelete(BSTNode *&bt,KeyType k)
{
BSTNode *p=bt,*f,*r,*f1;
f=NULL; //p指向待比较节点,f指向*p的双亲节点
while(p!=NULL && p->key!=k){ //查找值域为k的节点
f=p;
if(p->key > k)
p=p->lchild;
else
p=p->rchild;
}
if(p==NULL) //未找到值域为k的节点
return 0;
else if(p->lchild==NULL){ //*p为被删节点,若他无左子树。都是用右孩子代替
if(f==NULL)
bt=p->rchild;
else if(f->lchild==p){
f->lchild=p->rchild;
free(p);
}
else if(f->rchild==p){
f->rchild=p->rchild;
free(p);
}
}
else if(p->rchild==NULL){ //*p为被删节点,若他无右子树。都是用左孩子代替
if(f==NULL)
bt=p->lchild;
else if(f->lchild==p){
f->lchild=p->lchild;
free(p);
}
else if(f->rchild==p){
f->rchild=p->lchild;
free(p);
}
}
else{ //*p为被删节点,若他有左子树和右子树
f1=p;r=p->lchild; //查找*p的左子树中的最右下节点*r.它一定是无右子树的节点,*f1作为r的双亲
while(r->rchild!=NULL){
f1=r;
r=r->rchild;
}
if(f1->lchild==r) //无论是左孩子还是右孩子,都删除*r,用它代替*p
f1->lchild=r->rchild;
else if(f1->rchild==r)
f1->rchild=r->lchild;
r->lchild=p->lchild;
r->rchild=p->rchild;
if(f==NULL)
bt=r;
else if(f->lchild==p)
f->lchild=r;
else
f->rchild=r;
free(p);
}
return 1;
}
还是那句话,画个图就清晰了。
4. 红黑树(二叉平衡树):待续
5. hash查找:
最关键的就是找到一个好的hash函数,然后有好的解决冲突的方法。