这里的查找,是指找到关键字等于给定值的记录在表里的位置,或者说关键字等于给定值的元素在数组里的下标,对于一维数组,关键字就是数组里元素的值。前提是数组里不能有重复的值。
顺序查找,是把表里记录挨个与给定值比较,直到找到关键字等于给定值的记录。或者整个表里没有符合给定值的记录。要求表是线性表,顺序存储,或者链式存储。
对于顺序存储的、关键字已经排序的表,可以采用折半查找。效率得以提高,但这样的表,不适于经常的插入删除表里记录。依据公式 : mid = (start + end) / 2 。start是表里记录的起点下标,end是表里记录的终点下标。
类似于折半查找,我们也可以采用插值查找。其相对于折半查找,采用的 mid 值不同。依据公式 :
mid = start + (valForSearch - array[start])/(array[end] - array[start]) * (end - start) ,
valForSearch 是给定值。
这个是初中就学过的知识,已知线段的两端点坐标,当把线段按比例分成两部分,求分段点的坐标,如图:
在查找里能应用该公式的前提是,始终保证:
start <= mid <= end , array[start] <= array[mid] <= array[end] 。
否则对于 array[start] < valForSearch < array[start + 1] 的情况。程序会出错 。
同理,对于斐波那契查找的算法,其思路是依据了斐波那契数列的性质:
Fibonacci[ n ] = Fibonacci[ n - 1 ] + Fibonacci[ n - 2 ]. 把表里记录数补全增加到等于最临近的斐波那契数列的那一项,然后把表分成两部分,一部分含有Fibonacci[ n - 1 ] 项,另一部分含有
Fibonacci[ n - 2 ] 项,比较给定值在哪一区间里,按Fibonacci数列递减的方向,缩小待比较的表记录区间。直到表里记录数小于等于 2 项。同样要警惕表里没有给定值的情况。当 start + 1 = end ,且
array[start] < valForSearch < array[end] 时,结束循环,直接得判定结果。
综上所述,还是折半查找最为稳妥。mid 值的求法,依赖外界因素最少,最可靠。
然后是分块查找,首先要把表里记录的索引,即数组的下标,分块,依据元素值的大小。块之间是有序的,块内部是无序的。结合折半查找和顺序查找,也可以加快表的查询速度。同时,减小了建立索引的工作量。
以下是所有代码,程序建立思路如上所述,先是main函数所在源文件:
#include<iostream>
using namespace std;
#define MAXSIZE 30
extern void sequentialSearch(int array[],int length,int valForSearch);
extern void binarySearch(int array[], int length, int valForSearch);
extern void interpolationSearch(int array[], int length, int valForSearch);
extern void FibonacciSearch(int array[], int length, int valForSearch);
extern void blockSearch(int array[], int length, int valForSearch);
int main() {
int arrayA[] = {3,6,2,10,1,8,100,7,4,9};
sequentialSearch(arrayA,10,5);
cout << endl;
int arrayB[] = {1,2,3,4,5,6,7,8,10,11};
binarySearch(arrayB,10,9);
cout << endl;
interpolationSearch(arrayB,10,9);
cout << endl;
int arrayC[MAXSIZE] = {0,1,2,3,4,5,6,7,8,10,11,12,13,14,15,16,17,18,19,20,};
FibonacciSearch(arrayC,20,9);
cout << endl;
int arrayD[MAXSIZE] = { 8,14,6,9,10,22,34,18,19,31,40,38,54,66,
45,71,78,68,80,85,100,94,88,96,87 };
int length = 25;
blockSearch(arrayD,length,46);
return 0;
}
然后是各函数所在源文件:
#include<iostream>
using namespace std;
#define MAXSIZE 30
struct Block {
int valMin;
int valMax;
int index[10];
int length;
};
void printArray(int array[],int length) {
cout << "array : ";
for (int i = 0; i < length; i++) {
if (i % 10 == 0)
cout << endl;
printf("%4d",array[i]);
}
cout << endl;
}
void sequentialSearch(int array[], int length, int valForSearch) {
printArray(array,length);
if (array[0] == valForSearch) {
cout << valForSearch << " 的位置是 : 1"<<endl;
return;
}
array[0] = valForSearch;
int i = length - 1;;
while (array[i] != valForSearch)
i--;
if (i == 0)
cout << valForSearch << "is not in this array !" << endl;
else
cout << valForSearch << " 的位置是 :" << (i + 1) << endl;
}
void binarySearch(int array[], int length, int valForSearch) {
printArray(array,length);
int start = 0, end = length - 1,mid;
while (start <= end) {
mid = (start + end) / 2;
if (valForSearch < array[mid])
end = mid - 1;
else if (valForSearch > array[mid])
start = mid + 1;
else {
cout << valForSearch << " 的位置是 :" << mid + 1 << endl;
return;
}
}
cout << valForSearch << " is not in this array !" << endl;
}
void interpolationSearch(int array[], int length, int valForSearch) {
printArray(array, length);
int start = 0, end = length - 1, mid;
while (start <= end) {
if (valForSearch < array[start])
break;
mid = start + (end - start) * (valForSearch - array[start])/(array[end] - array[start]);
if (valForSearch < array[mid])
end = mid - 1;
else if (valForSearch > array[mid])
start = mid + 1;
else {
cout << valForSearch << " 的位置是 :" << mid + 1 << endl;
return;
}
}
cout << valForSearch << " is not in this array !interpolation serch has bug!" << endl;
}
int Fibonacci(int index) {
if (index == 0 || index == 1)
return 1;
else
return Fibonacci(index - 1) + Fibonacci(index - 2);
}
void FibonacciSearch(int array[], int length, int valForSearch) {
printArray(array,length);
int fiboindex;
for (fiboindex = 0; Fibonacci(fiboindex) < length; fiboindex++);
for (int i = length; i < Fibonacci(fiboindex); i++)
array[i] = array[length - 1];
printArray(array,Fibonacci(fiboindex));
int start = 0, end = Fibonacci(fiboindex) - 1,mid;
while (start <= end) {
if (fiboindex <= 2 && valForSearch > array[start] && valForSearch < array[end])
break;
mid = start + Fibonacci(fiboindex - 1) - 1;
if (valForSearch < array[mid]) {
end = mid;
fiboindex--;
}
else if (valForSearch > array[mid]) {
start = mid;
fiboindex = fiboindex - 2;
}
else {
cout << valForSearch << " 的位置在 :" << mid + 1 << endl;
return;
}
}
cout << valForSearch << " is not in array !" << endl;
}
void blockSearch(int array[], int length, int valForSearch) {
Block blocks[5];
blocks[0].length = 0; blocks[0].valMin = 0; blocks[0].valMax = 20;
blocks[1].length = 0; blocks[1].valMin = 21; blocks[1].valMax = 40;
blocks[2].length = 0; blocks[2].valMin = 41; blocks[2].valMax = 60;
blocks[3].length = 0; blocks[3].valMin = 61; blocks[3].valMax = 80;
blocks[4].length = 0; blocks[4].valMin = 81; blocks[4].valMax = 100;
for(int i = 0; i < length; i++) {
int j;
for (j = 0; j < 5; j++)
if (array[i] >= blocks[j].valMin && array[i] <= blocks[j].valMax)
break;
blocks[j].index[blocks[j].length] = i;
blocks[j].length++;
}
printArray(array,length);
int start = 0, end = 4, mid;
while (start <= end) {
mid = (start + end) / 2;
if (valForSearch > blocks[mid].valMax)
start = mid + 1;
else if (valForSearch < blocks[mid].valMin)
end = mid - 1;
else {
for (int i = 0; i < blocks[mid].length; i++)
if (valForSearch == array[blocks[mid].index[i]]) {
cout << valForSearch << " 的位置在 :" << blocks[mid].index[i] + 1 << endl;
return;
}
break;
}
}
cout << valForSearch << " is not in the array !" << endl;
}
测试结果如下:
之所以举例里都找不到,是因为对找到的情况测试过了。
谢谢阅读