一:查找的基本概念
(1)查找表: 由同一类型的数据元素构成的集合
1)静态查找表:只做查找操作的查找表
1)查询某个“特定数据”元素是否在查找表中。
2)检索某个特定的数据元素和各种属性;
2)动态查找表:在查找过程中同事插入查找表中不存在的数据元素,或者从查找表中删除已经存在的某个数据元素。
1)查找时插入元素
2)查找时删除元素
(2)关键字: 数据元素中某个数据项的值。
1)主关键字:关键字能唯一的标识一个数据元素(记录)
2)次关键字: 可以识别多个数据元素的关键字
(3)查找:根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素
二:顺序表查找:
(1)顺序表查找算法:时间复杂度为O(n)
/顺序查找,a为数组,n为要查找的数组元素个数,key为要查找的关键字;/
int Sequential_Serch(int *a, int n, int key)
{
int i;
for(i = 1; i <= n; i++)
{
if(a[i] == key)
return i;
}
return 0;
}
**(2)顺序表查找优化:**时间复杂度为O(n)
/设置哨兵;/
int Sequential_Serch(int a*, int n, int key)
{
int i = n; //循环从数组尾部开始
a[0] = key; //设置a[0]为关键字,我么称之为“哨兵”;
while(a[i] != key)
{
i--;
}
return i; //返回0说明查找失败。
}
三:有序表查找:
(1)折半查找(二分查找):前提是表中的记录必须是关键码有序(通常从小到大):时间复杂度为O(logn);
int Binary_Serch(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即为查找到的位置
}
return 0;
}
**(2)插值查找:**讲折半的公式调整后为: mid = low + (key - a[low]) / (a[high] - a[low]) * (high - low)
时间复杂度仍为O(logn)
int Insert_Serch(int *a, int n; int key)
{
int low, high, mid;
low = 1; //定义最低下标为记录首位;
high = n; //定义最高下标为记录末位
while(low <= high)
{
mid = low + (key - a[low]) / (a[high] - a[low]) * (high - low); //插值
if(key < a[mid]) //若查找值比中值小
{
high = mid -1; //最高下标调整到中位下标小一位
}
else if(key > a[mid]) //若查找值比中值大
{
low = mid + 1; //最低下标调整到中位下标大一位
}
else
return mid; //若相等,则说明mid即为查找到的位置
}
return 0;
}
(3)斐波拉契查找:利用黄金分割原理实现。 利用F[k] = F[k-1] + F[k-2]的变形,时间复杂度O(logn)
先需要你一斐波拉契数列的数组
下标 0 1 2 3 4 5 6 7 8 9 10
F 0 1 1 2 3 5 8 13 21 34 …
int Fibonacci_Serch(int *a, int n, int key)
{
int low, high, mid;
int 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 < mid)
{
high = mid - 1;
k = k -1; //斐波拉契数列下标减一位
}
else if(key > mid)
{
low = mid + 1;
k = k-2; //斐波拉契数列下标减两位
}
else
{
if(mid <= n)
return mid; //若想等,说明mid为查找到为位置
else
return n; //若mid>n,说明为补全数据,返回n
}
}
return 0;
}
这里之所以是F[K]-1而不是F[k],是因为F[k]-1 = F[k-1]-1 + F[k-2]-1 + 1;加1加的是mid那个位置)
而F[k] != F[k-1] + F[k-2] + 1
从low到high一共是F[k]-1个数据,减一是要去掉mid
|low |mid| high|
↖F[k-1] -1↗ ↖ F[k-2]-1↗