PS:都是自己认为目前需要掌握熟悉了解的,并不是所有,日后需要的时候再一一补充
查找表:由同一类型的数据元素(或记录)构成的集合。
关键字:数据元素中某个数据项的值。
若此关键字可以唯一标识一个记录,则称此关键字为主关键字。
如果此关键字可以识别多个数据元素(或记录),则称为次关键字。
查找就是根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素(或记录)。
查找表分为两大种:静态查找表和动态查找表。
1. 静态查找表:只作查找操作的查找表。
(1) 查询某个“特定的”数据元素是否在查找表中。
(2)检索某个“特定的”数据元素的各种属性。
2. 动态查找表:在查找过程中,同时插入不存在的数据元素或者删除数据元素。
(1) 查找时插入元素。
(2) 查找所删除元素。
顺序表的查找
1 普通算法
int Ordinary_Find(int ary[], int target)
{
for (int i = 1; i < =ary.Length; i++)
{
if (ary[i] == target)
{
//找到了就返回找到的位置
return i;
}
}
//没找到就返回-1,表示没找到
return -1;
}
2 优化之后
int Find(int ary[] , int target)
{
int i;
a[0]=target;
i=ary.length;
while(a[i]!=target)
{
i--;
}
return i;
}
有序表的查找
1. 折半查找
int BiSearch(int data[], int key, int n)
{
int mid,low,high;//中间位置
low=1;
high=n;
if (low > high)
{
return -1;
}
while(low <= high)
{
mid = (low + high) / 2;
if (key == data[mid] )
{
return mid;
}
else if (data[mid] < key)
{
low = mid + 1;
}
else if (data[mid] > key)
{
high = mid - 1;
}
}
return -1;
}
2. 插值查找
我们在一本英汉字典中寻找单词“worst”,我们决不会仿照对半查找(或Fibonacci查找)那样,先查找字典中间的元素,然后查找字典四分之三处的元素等等. 事实上,我们是在所期望的地址(在字典的很靠后的地方)附近开始查找的,我们称这样的查找为插值查找。
数据不仅是已被排好序的,而且呈现均匀分布特征。
int Insert_search(int *a, int key, int n)
{
int pos, low, high;
low = 0,high = n - 1;
while(low <= high){
pos = ((key - a[low]) * (high - low )) / (a[high] - a[low]) + low;
if(a[pos] < key){
low = pos + 1;
} else if(a[pos] == key){
return pos;
} else{
high = pos - 1;
}
}
return -1;
}
3. 斐波那契查找
ps 不会,没深入了解
线性索引查找
有时候数据集可能增长非常快,例如,某些微博网站或大型论坛的帖子和回复总数每天都是成百万上千万条,或者一些服务器的日志信息记录也可能是海量数据,要保证记录全部是按照当中的某个关键字有序,其时间代价是非常高昂的,所以这种数据都是按先后顺序存储的。
对于这样的查找表,我们如何能够快速 查找到需要的数据呢?办法就是----索引
索引是 了加快查找速度而设计的一种数据结构。
索引就是把一个关键字与它对应的记录相关联的过程,一个索引由若干个索引项构成,每个索引项至少应包含关键字和其对应的记录在存储器中的位置等信息。
索引按照结构可以分为线性索引、树形索引和多级索引。我们这里就只介绍线性索引技术。所谓线性索引就是将索引项集合组织为线性结构,也称为索引表。我们重点介绍三个线性索引:稠密索引、分块索引、和倒排索引。
稠密索引
它是指线性索引中,将数据集中的每个记录对应一个索引项。
对于稠密索引这个索引表来说,索引一定是按照关键码有序排列的。
索引项有序也就意味着,我们要查找关键字时,可以用到折半、插值、斐波那契等有序查找算法,大大提高效率。
比如查找上表中的18。如果不用索引表,需要6次。而用左侧的索引表,折半两次就可以找到18对应的指针。
这显然是稠密索引优点,但是如果数据集非常大,比如上亿,那也就意味着索引也得同样的数据集长度规模,对于内存有限的计算机来说,可能就需要反复去访问磁盘,查找性能反而大大下降了。
分块索引
稠密索引因为索引项与数据集的记录个数相同,所以空间代价很大。为了减少索引的个数,我们可以对数据集进行分块,使其分块有序,然后再对每一块建立一个索引项,从而减少索引项的个数。
分块有序,是把数据集的记录分成若干块,并且这些块需要满足两个条件:
l 块内无序,即每一块内的记录不要求有序。当然,你如果能够让块内有序对查找来说更理想,不过这就要付出大量时间和空间代价,因此通常我们不要求块内有序
l 块间有序,例如要求第二块所有记录的关键字均要大于第一块中所有记录的关键字,第三块的所有记录的关键字均要大于第二块的所有记录关键字….因为只有块间有序,才有可能在查找时带来效率。
对于分块有序的数据集,将每块对应一个索引项,这种索引方法叫做分快索引。
n 最大关键码:它存储每一块中的最大关键字,这样的好处就是可以使得在它之后的下一块中最小关键字也能比这一块最大的关键字要大
n 存储了块中的记录个数,以便于循环时使用
n 用于指向块首数据元素的指针,便于开始对这一块中的记录进行遍历。
分块索引是分两步进行:
1. 在分块索引表中查找要查关键字所在的块。由于分块索引表是块间有序的,因此很容易利用折半、插值等算法得到结果。
2. 根据块首指针找到相应的块,并在块中顺序查找关键码。因为块中可以是无序的,因此只能顺序查获。