我们前面提到的几种高效查找方法都是基于有序的基础上的,但是实际上,很多数据集可能增长非常快。例如空间动态信息等,
对于这样的查找表,我们若是保证记录全部按照当中某个关键字有序,其维护的时间代价非常高,
所以这种数据通常是按照先后顺序存储。
对于这样的查找表,我们如何快速的查找到所需要的数据?---》通过索引
数据结构的最终目的就是提高数据的处理速度,索引是为了加快查找速度而设计的一种数据结构。索引就是把一个关键字与他对应的记录相关联的过程
一个索引由若干个索引项构成,每个索引项至少应包含关键字和其对应的记录在存储器中的位置等信息。
索引技术是组织大型数据库以及磁盘文件的一种重要技术。
索引按照结构可以分为线性索引,树形索引和多级索引。
所谓线性索引就是将索引项集合组织为线性结构,也称为索引表。
下面我们需要了解三种线性索引索引方式:稠密索引,分块索引和倒排索引
一:稠密索引
稠密索引文件的每个记录都有一个索引项,记录在数据区存放是任意的,但索引是按序的,这种索引称为稠密索引。
稠密索引是指在线性索引中,将数据集中的每个记录对应一个索引项。

由上图可以知道:对于稠密索引这个索引表而言,索引项一定是按照关键码有序的排列。
优点
索引项有序也就意味着,我们要查找关键字时,可以用折半,插值及斐波那契等有序查找算法。
比如要查找关键字18的记录,如果直接从右侧的数据表中查找,那只能顺序查找。
需要查找6次才可以看到结果
而如果是从侧的索引表中查找,只需两次折半查找就可以得到18对应的指针。对应找到结果。
好吧!以上显然是稠密所以优点。
缺点
如果数据集非常大,比如上亿,那也就意味着索引也得同样的数据集长度规模。
对于内存有限的计算机来说,可能就需要反复去访问磁盘,查找性能大大下降。
稠密索引文件的索引查找、更新都较方便,但由于索引项多,占用空间较大。
案例实现:年级最多1000个学生,现在进行稠密索引
#define MAXSIZE 1000
typedef struct _Student //记录
{
int No;
char name[32];
bool sex;
struct _Student* next;
}Student;
typedef struct _Index //索引
{
int No;
Student* ind;
}Index;
![]()
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAXSIZE 1000
typedef struct _Student //记录
{
int No;
char name[32];
bool sex;
struct _Student* next;
}Student;
typedef struct _Index
{
int No;
Student* ind;
}Index;
Student* S;
Index I[MAXSIZE];
void AddInfo(int No, char* name, int sex)
{
//创建数据
Student *ST;
int loc,i;
ST = (Student *)malloc(sizeof(Student));
strcpy(ST->name, name);
ST->No = No;
ST->sex = sex;
ST->next = S;
S = ST;
//插入索引
if (Insert_Search(I, I[0].No, ST->No, &loc)==-1)
{
for (i = I[0].No + 1; i > loc; i--)
{
I[i].No = I[i - 1].No;
I[i].ind = I[i - 1].ind;
}
I[i].No = ST->No;
I[i].ind = ST;
I[0].No++; //存储数组大小
}
}
int Search_Info(int no,Student** stu)
{
int loc;
loc = Insert_Search(I, I[0].No, no, &loc);
if (loc != -1)
*stu = I[loc].ind;
else
return -1;
return 1;
}
int Insert_Search(Index *ind, int n, int key,int *loc)
{
int low, high, mid;
low = 1;
high = n;
if (n <= 1)
mid = n+1;
if (key<I[low].No)
{
*loc = low;
return -1;
}
else if (key > I[high].No)
{
*loc = high + 1;
return -1;
}
else
{
while (low < high)
{
mid = low + (key - ind[low].No) / (ind[high].No - ind[low].No)*(high - low);
if (ind[mid].No < key)
low = mid + 1;
else if (ind[mid].No>key)
high = mid - 1;
else
return mid;
}
mid++;
}
*loc = mid;
return -1;
}
int main()
{
char name[32];
int no;
int sex;
char cmd;
Student* info;
I[0].No = 0;
while (1)
{
printf("input CMD:\n");
scanf("%c", &cmd);
switch (cmd)
{
case 'A':
printf("input name:");
scanf("%s", name);
printf("input student number:");
scanf("%d", &no);
printf("input student sex:(1/0)");
scanf("%d", &sex);
AddInfo(no, name, sex);
break;
case 'S':
printf("input number to find:");
scanf("%d", &no);
if (Search_Info(no, &info) == 1)
printf("find student:%s %d %d", info->name, info->No, info->sex);
else
printf("no find");
break;
case 'Q':
exit(0);
default:
break;
}
getchar();
}
}
全部代码