数据结构(10)之查找

1 前言

     这节我们简单的介绍一下常见的查找算法。

2 详述

2.1 查找概论

查找表(Search Table)是由同一类型的数据元素(或记录)构成的集合。

关键字(Key)是数据元素中某个数据项的值,又称为键值。

可以识别多个数据元素(或记录)的关键字,我们称为次关键字(Secondary Key)。

查找(Searching)就是根据给定的某个值,在查找中确定一个其关键字等于给定的数据元素(或记录)。

查找按照操作方式来分有两大种:静态查找表和动态查找表。

静态查找表(Static Search Table):只做查找操作的查找表。

(1)查询某个“特定的”数据元素是否在查找表中。

(2)检索某个“特定的”数据元素和各种属性。

动态查找表(Dynamic Search Table):在查找过程中同时插入查找表中不存在的数据元素,或者从查找表中删除已经存在的某个数据元素。

(1)查找时插入数据元素。

(2)查找时删除数据元素。

2.2 顺序查找表

顺序查找(Sequential Search)又叫线性查找,是最基本的查找技术,它的查找过程是:从表第一个(或最后一个)记录开始,逐个进行记录的关键字和给定值比较,若某个记录的关键字和给定值相等,则查找成功,找到所查找的记录;如果知道最后一个(或第一个)记录,其关键字和给定值比较都不相等,则表中没有所查的记录,查找不成功。

2.2.1 顺序查找算法

代码实现:

 

/*顺序查找,a为数组,n为要查找的数组个数,key为要查找的关键字*/
int Sequntial_Search(int *a,int n,int key)
{
    int i;
    for(i =1;i<=n;i++)
    {
        if(a[i]==key)
            return i;
    }
    return 0;
}


 

2.2.2 顺序查找优化

 

/*有哨兵顺序查找*/
int Sequential_Search2(int *a,int n,int key)
{
    int i;
    a[0]==key;  /*设置a[0]为关键字值,我们称之为“哨兵”*/
    i=n;        /*循环从数组尾部开始*/
    while(a[i]!=key)       
    {
        i--;
    }
    return i;       /*返回0则说明查找失败*/
}


 

时间复杂度为 O(n)。

2.3 有序表查找

2.3.1 折半查找

折半查找(Binary Search)技术,又称为二分查找。它的前提是线性表中的记录必须是关键码有序(通常是从小到大有序),线性表必须采用顺序存储。折半思想:有序表中,取中间记录作为比较对象,若给定值与中间记录的关键字相等,则查找成功;若给定值小于中间记录的关键字,则在中间记录的左半区继续查找;若给定值大于中间记录的关键字,则在中间记录的右半区继续查找。不断重复上述过程,知道查找成功,或所有查找区域无记录,查找失败为止。

算法实现:

 

/*折半查找*/
int Binary_Search(int *a,int n,int key)
{
    int low,high,mid;
    low = 1;              /*定义最低下标为记录首位*/
    high = n;        /*定义最高下标为记录末位*/
    while(low<=high)
    {
        mid = (low+high)/2;       /*折半*/
        if(key<a[mid])           /*若查找值比中值小*/
            high = mid -1;       /*最高下标调整到中位下标小一位*/
        else if(key>a[mid])     /*若查找值比中值大*/
            low = mid+1;       /*最低下标调整到中位下标大一位*/
        else
            return mid;      /*若相等则说明mid即为查找到的位置*/
    }
}

 

 

时间复杂度O(logn)。

2.3.2 插值查找

插值查找(Interpolation Search)是根据要查找的关键字key与查找表中最大最小记录的关键字比较厚的查找方法,其核心就在于插枝的计算公式(key-a[low])/(a[high]-a[low])。

 

mid = low +(high-low)*(key-a[low])/(a[high]-a[low])。


 

时间复杂度为O(logn),但是对于表长较大,而关键字分布又比较均匀的查找表来说,插枝算法的平均性能比折半查找要好很多。

2.4斐波那契查找

斐波那契数列:

程序运行:

 

/*斐波那契查找*/
int Fibonacci_Search(int *a,int n,int key)
{
    int low,high,mid,i,k;
    low = 1;      /*定义最低下标为记录首位*/
    high = n;     /*定义最高下标为记录末尾*/
    k = 0;
    while(n>F[k]-1)      /*计算n位于斐波那契数列的位置*/
        k++;
    for(i = n;i<F[k]-1;i++)        /*将不满数值补全*/
        a[i] = a[n];
    while(low<=high)
    {
        mid = low +F[k-1]-1;     /*计算当前分隔的下标*/
        if(key<a[mid])               /*若查找记录小于当前分隔记录*/
        {
            high = mid-1;           /*最高下标调整到分隔下标mid-1处*/ 
            k = k-1;                     /*斐波那契数列下标减一位*/
        }
        else if(key>a[mid])     /*若查找记录大于当前分隔记录*/
        {
            low = mid+1;        /*最低下标调整到分隔下标mid+1处*/
            k=k-2;                   /*斐波那契数列下标减两位*/
        }
        else
        {
            if(mid<=n)            /*若想等说明mid即为查找到得位置*/
                return mid;
            else
                return n;           /*若mid>n说明是补全数值,返回n*/
        }
    }
    return 0;
}


 

时间复杂度O(logn)。

2.5 线性索引查找

索引就是把一个关键字与它对应的记录相关联的过程。

所谓线性索引就是将索引项集合组织为线性结构,也称为索引表。

2.5.1 稠密索引

在线性索引中,将数据集中的每个记录对应一个索引项。

对于稠密索引这个索引表来说,索引项一定是按照关键码有序的排列。

2.5.2 分块索引

分块有序,是吧数据集的记录分成了若干块,并且:

·快内无序

·块间有序:第二块所有的记录的关键字均大于第一块中所有记录的关键字,第三块的所有记录的关键字均大于第二块的所有记录的关键字。

分块索引的索引项结构分为三个数据项:

·最大关键码,它存储每一块中的最大关键字

·存储了块中的记录个数

·用于指向首数据的指针,便于开始对这一块中记录进行遍历

时间复杂度高于顺序查找,低于折半查找。

2.5.3 倒序索引

索引结构:

·次关键码,例如上面的“英文单词”

·记录号表,例如上面的“文章编号”

其中记录号表存储具有系统次关键字的所有记录的记录号(可以是指向记录的指针或者是该记录的主关键字)。这样的索引方法就是倒序索引(inverted index)。

2.6 二叉树排序

二叉排序树(Binary Sort Tree),又称为二叉查找树。它或者是一棵空树,或者是具有下列性质的二叉树。

·若它的左子树不空,则左子树上所有结点的值均小于它的根结构的值;

·若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;

·若它的左,右子树也分别为二叉排序树。

查找实现

 

/*递归查找二叉排序树T种是否存在key*/
/*指针f指向T的双亲,其初始调用值为NULL*/
/*若查找成功,则指针p指向该数据元素结点,并返回TRUE*/
/*否则指针p指向查找路径上访问的最后一个结点并返回FALSE*/
Status SearchBST(BiTree T,int key,BiTree f,BiTree *p)
{
    if(!T)
    {
        *p = f;
        return FALSE;
    }
    else if(key == T->data)
    {
        *p = T;
        return TRUE;
    }
    else if(key<T->data)
        return SearchBST(T->lchild,key,T,p);  /*在左子树继续查找*/
    else
        return SearchBST(T->child,key,T,p);   /*在右子树继续查找*/
}

 

 

3 结语

    以上是所有内容,希望对大家有所帮助。

 

posted on 2013-10-11 16:53  我的小人生  阅读(213)  评论(0编辑  收藏  举报