算法索引查找

索引查找:

索引查找是在索引表和主表(即线性表的索引存储结构)上进行的查找,但需要先建立索引表,索引表就类似图书的目录,能大提高查找效率。

给顺序表创建索引表:
typedef struct Stduent
{
    int id;
    char name[20];
    char sex;
    short age;
    float score;
}Student;
​
Student stu[10000]; //  主表
​
//  索引表元素结构
typedef struct Index
{
    int id;
    void* addr;
}Index;
​
//  索引表
Index indexs[10000];
​
//  对主表与索引表之间建立索引
void create_index(Student* stu,Index* indexs,size_t len)
{
    for(int i=0; i<len; i++)
    {
        indexs[i].id = stu[i].id;
        indexs[i].addr = stu+i;
    }
}
//  注意:建立索引表后,后面使用索引查找的是索引表,再通过找到的索引表中记录的主表元素的位置信息,来最终找到待查找的数据元素
//  注意:索引表如何建立索引,根据实际需求来选择
索引表的顺序查找:
//  它比直接查询数据的主表的跳转速度要快,如果使用stu[i]查找,i每加1,要跳转过sizeof(Student)个字节数,如果使用索引表indexs[i]查询,i每加1,则只需要跳转sizeof(Index)个字节数,比主表跳转字节数要少。
//  如果主表的数据不存在内存而是存储在磁盘上,而索引表是建立在内存中,通过索引表访问效率、速度远高于访问磁盘的主表
int order_index_search(Index* indexs,size_t len,int id)
{
    for(int i=0; i<len; i++)
    {
        if(indexs[i].id == id)
            return i;
    }
    /*
    for(int i=0; i<len; i++)
    {
        if(stu[i].id == id)
            return i;
    }
    */
}
索引表二分查找:
//  需要对索引表先排序
//  对索引表排序的效率和速度要远比直接对主表的排序要快
void sort_index(Index* indexs,size_t len)
{
    for(int i=0; i<len-1; i++)
    {
        int min = i;
        for(int j=i+1; j<len; j++)
        {
            if(indexs[j].id < indexs[min].id)
                min = j;
        }
        if(min != i)
        {
            Index temp = indexs[min];
            indexs[min] = indexs[i];
            indexs[i] = temp;
        }
    }
}
​
//  对索引表进行二分查找
//  因为索引表已经重新排序了,而主表没有排序过,所以不能返回在索引表中找到元素的下标,该下标与主表对应元素的下标很可能不一致了,所以需要直接返回主表对应元素的地址
Student* binary_index_search(Index* indexs,size_t len,int id)
{
    int l = 0, r = len-1;
    while(l <= r)
    {
        int p = (l + r)/2;
        if(indexs[p].id == id)
            return indexs[p].addr;
        if(id < indexs[p].id)
            r = p-1;
        if(id > indexs[p].id)
            l = p+1;
    }
    return NULL;
}
给链表创建索引表:
//  给链表head创建一张顺序的索引表 表中的元素是ListNode* 用来指向链表中的节点 
//  返回值是返回索引表首地址,len_i输出型参数,返回索引表中元素的个数
ListNode** create_index_list(ListNode* head,size_t* len_i)
{
    if(NULL == head || NULL == len_i) return NULL;
    //  索引表的长度
    *len_i = 0;
    ListNode** indexs = NULL;
    //  遍历链表head 给每个节点建立普通索引
    for(ListNode* n=head; NULL!=n; n=n->next)
    {
        //  申请索引表元素ListNode*的内存
        indexs = realloc(indexs,sizeof(ListNode*)*(*len_i+1));
        //  让索引表中的最后一个元素指向对应的链表节点
        indexs[(*len_i)++] = n;
    }
    
    //  对索引表进行排序,交换索引表中指针的指向
    for(int i=0; i<(*len_i)-1; i++)
    {
        int min = i;
        for(int j=i+1; j<*len_i; j++)
        {
            if(indexs[j]->data < indexs[min]->data)
                min = j;
        }
        if(min != i)
        {
            //  交换索引表中指针的指向 不修改链表
            ListNode* temp = indexs[min];
            indexs[min] = indexs[i];
            indexs[i] = temp;
        }
    }
}
​
//  链表的二分查找,本质上是对顺序的索引表进行二分
int binary_list_index_search(ListNode** indexs,size_t len,int key)
{
    int l = 0, r = len - 1;
    while(l <= r)
    {
        int p = (l + r)/2;
        if(indexs[p]->data == key)
            return p;
        if(key < indexs[p])
            r = p-1;
        if(key > indexs[p])
            l = p+1;
    }
    return -1;
}
索引查找的优点:
  • 对于顺序表的顺序查找,索引查找可以缩短数据的查找跳转范围

  • 对于顺序表的二分查找,通过排序索引表也能提高排序的速度

  • 对于链式表,可以先建立顺序的索引表后,进行之前无法实现的二分查找了

索引查找的缺点:
  • 使用了额外的存储空间来创建索引表,是一种典型的以空间换时间的算法策略

索引查找的使用场景:
  • 如果针对的是内存中的顺序表中的数据,通过索引查找提升的速度和效率其实并不是很明显,毕竟内存的运算速度很快

  • 但是对于存储在机械硬盘上的数据,通过在内存中建立对应硬盘数据的索引表,访问起来提升的效率就很多了,因此在一些常用的数据库中的索引查找使用非常多

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值