- 搜索,就是在数据集合中寻找满足某种条件的数据元素。最常见的一种方式是事先给定一个值,在集合中找出其关键码等于给定值的元素。搜索的结果通常有两种可能:一种可能是搜索成功,即找到满足条件的数据元素。这时,作为结果,可报告该元素在结构中的位置,还可以进一步给出该元素中的具体信息。后者在数据库中叫做检索。另一种可能是搜索不成功,或搜索失败。作为结果,也应该报告一些信息,如失败标志、失败位置等。
- 通常称用于搜索的数据集合为搜索结构,它是由同一数据类型的元素(或记录)组成。在搜索结构中,每一个元素(或记录)称作对象,搜索结构可用对象类来定义。
- 在每一个对象中由若干属性,其中应当有一个属性,其值可唯一地标识这个对象。他称为关键码。使用基于关键码的检索,搜索结果应是唯一的。但在实际应用时,搜索条件是多方面的,例如,图书馆中应该允许按书名搜索、按作者搜索,…这样,可以使用基于属性的搜索方法,但搜索结果可能不唯一。
- 静态查找就是我们平时概念中的查找,是“真正的查找”。之所以说静态查找是真正的查找,因为在静态查找过程中仅仅是执行“查找”的操作,即:(1)查看某特定的关键字是否在表中(判断性查找);(2)检索某特定关键字数据元素的各种属性(检索性查找)。这两种操作都只是获取已经存在的一个表中的数据信息,不对表的数据元素和结构进行任何改变,这就是所谓的静态查找。
- 动态查找不像是“查找”,更像是一个对表进行“创建、扩充、修改、删除”的过程。动态查找的过程中对表的操作会多两个动作:(1)首先也有一个“判断性查找”的过程,如果某特定的关键字在表中不存在,则按照一定的规则将其插入表中;(2)如果已经存在,则可以对其执行删除操作。动态查找的过程虽然只是多了“插入”和“删除”的操作,但是在对具体的表执行这两种操作时,往往并不是那么简单。
顺序搜索
顺序搜索是最基本的搜索方法之一。顺序搜索又称为线性搜索,主要用于在线性表中进行搜索。、
int ordersearch(int a[], int n, int des){
int i;
for(i=0; i<n; i++){
if(des==a[i])
return 1;
}
return 0;
}
基于有序顺序表的顺序搜索和折半搜索
//顺序搜索
int ordersearch(int a[], int n, int des){
int i;
for(i=0; i<n; i++){
if(des==a[i])
return 1;
else if(des<a[i]) break;
}
return 0;
}
//折半搜索非递归实现
public int bsearch(int[] a, int n, int value) {
int low = 0; int high = n - 1;
while (low <= high) {
int mid = (low + high) / 2;
if (a[mid] == value) {
return mid;
} else if (a[mid] < value) {
low = mid + 1;
} else {
high = mid - 1;
}
}
return -1;
}
// 二分查找的递归实现
public int bsearch(int[] a, int n, int val) {
return bsearchInternally(a, 0, n - 1, val);
}
private int bsearchInternally(int[] a, int low, int high, int value) {
if (low > high) return -1;
int mid = low + ((high - low) >> 1);
if (a[mid] == value) {
return mid;
} else if (a[mid] < value) {
return bsearchInternally(a, mid+1, high, value);
} else {
return bsearchInternally(a, low, mid-1, value);
}
}
斐波拉契搜索
若一个具有n个元素的有序表,n=F(k)-1,即比某个斐波拉契数少1.如果n不是正好等于某个斐波拉契数,可以增加一些虚元素,使其达到某个斐波拉契数。例如,n=F(7)-1=12,可取low=1,hight=n=12,mid=F(6)=8。
public static int fibonacciSearch(int[] a, int n, int key) {
int low = 0;
int high = n - 1;
int F[] = new int[max_size];
fibonacci(F);//构建斐波那契数组
//计算 n 位于斐波那契数列的位置
int k = 0;
while (n > F[k] - 1)
++k;
//将数组a扩展到F[k]-1的长度,即增加了虚元素
int tmp[];
tmp = new int[F[k] - 1];
System.arraycopy(a, 0, tmp, 0, n);
for (int i = n; i < F[k] - 1; ++i)
tmp[i] = a[n - 1];//用数组最后一个元素扩展
while (low <= high) {
int mid = low + F[k - 1] - 1;//借助斐波纳契数确定位置,减1是low从0开始
if (key < tmp[mid]) {
high = mid - 1;
k -= 1;
} else if (tmp[mid] < key) {
low = mid + 1;
k -= 2;
} else {
if (mid < n)
return mid;
else
return n - 1;
}
}
tmp = null;
return -1;
}
- 当n很大(n>10)时,这种搜索方法叫做黄金分割法,其平均性能比折半搜索好。但是最坏情况时,性能比折半搜索差。搜索成功的平均搜索长度也是O(log2n)。这种方法的优点时找中间点mid不需要做除法,只需做加减法即可。