顺序查找
算法思想
从表的一端开始,用给定的值value与表中各个结点的关键字进行比较:
若查找成功,输出相等值的下标
若查找失败,即表中所有结点的关键字值都不等于value
监视哨
由于在遍历的时候,每次都需判断越界,这会花费一些时间。此时,设置一个监视哨来降低时间花销
实现:给表头(索引为0)赋予要查找的值value,且遍历从表尾开始,使得每次校对数据时,都不用判断越界。因为无论如何,都能匹配成功而停止遍历。若成功匹配时,所得到索引为0,则表示并未查找到想要的数据,其实是匹配失败了。
实例
若要查找25,则会在索引为4时匹配成功
若要查找52,匹配成功时,索引为0,则表示要查找的数据并不在此表中
具体实现
实现:
/**
* 设置监视哨,完成数据查询
* @param list 列表
* @param target 查询的目标
* @return 查询的结果(索引为0表示未查找到,-1表示在首位)
*/
public static int seekTarget(int list[], int target) {
//提取首位数据
int a = list[0];
if(a == target) {
return -1;//表示在首位
}
//设置监视哨
list[0] = target;
//获取遍历开始处
int index = list.length-1;
//遍历,判断(不需要判断是否越界)
while(list[index] != target) {
index--;
}
//复原
list[0] = a;
return index;
}
测试:
时间及空间复杂度
①时间
最好:位于末尾,查找n次
最坏:位于首位,查找一次
即,平均时间复杂度为T(n) = O(n)
②空间
S(n) = O(1)
二分查找
先决条件
表中结点按关键字有序,且顺序(一维数组)存储
算法思想
求有序表的中间位置mid
若value[mid].key == target,查找成功
若value[mid].key > target,则在右子表中继续查找
若value[mid].key < target,则在左子表中继续查找
核心:取中,比较
实例
若查找目标为45:
①初始化两个指针i(指向头,1),j(指向尾,11)
②i < j,取中,比较:mid=(i+j)/2=6,value[6]<45,则 i=mid+1=7
③i < j,取中,比较:mid=(i+j)/2=9,value[9]>45,则 j=mid -1=8
④i < j,取中,比较:mid=(i+j)/2=7,value[7]>45,则 j=mid -1=6
⑤i > j,停止,未查找到
Ps:关于为什么要使得 i/j = mid -1,因为此时mid已经判断过了,属于无用数据,则可省去提高效率;并且不这样的话,还会造成死循环
具体实现
/**
* 根据数据进行查找
* @param seek 数据
* @return 成功返回索引,失败返回-1
*/
public int binarySeek(int[] data, int seek) {
int Ri = 0; //右边查找
int Le = data.length - 1; //左边查找
while(Ri <= Le) {
int mid = (Le + Ri)/2;
if(data[mid] == seek) {
return mid;
}else if(seek < data[mid]) {
Le = mid - 1;
}else {
Ri = mid + 1;
}
}
return -1;
}
测试:
时间及空间复杂度
①时间
T(n) = O(log2n)
②空间
S(n) = O(1)