1、顺序查找
又称作线性查找,主要用于在线性表中进行查找。适用于对一般无序线性表的查找。基本思想:从线性表的一端开始查找,逐个检查关键字是否满足给定的条件。
2、折半查找
用于在有序的线性表中进行查找。基本思想:首先将给定的key值与线性表中中间位置的元素进行比较,若相等则查找成功,若不相等,则在线性表的中间元素之外的前半部分或后半部分进行查找。如此重复。
假设查找的数组区间为 [min,max],min 代表起始索引,max 代表结束索引,T 代表需要查找的值。
第一步:确定该区间的中间位置 K;
第二步:将查找的值 T 与 array[k] 比较。若相等,查找成功返回此位置;否则确定新的查找区域,继续折半查找;
第三步:若 array[k]>T,由数组的有序性可知 array[k,k+1,……,max] 中的每个值都大于 T,故新的区间为 array[min,……,K-1],若 array[k]<T,同理可得新的查找区间为 array[k+1,……,max]。
代码如下:
package day41;
public class DataArray {
/**
* @Description: 一个内部类
* 在书上通常是用的int类型,这里根据闵老师的文章设计的键值类型数据
*/
class DataNode {
//键值
int key;
//数据
String content;
public DataNode(int key, String content) {
this.key = key;
this.content = content;
}
@Override
public String toString() {
return "(" + key + "," + content + ")";
}
}
//数组
DataNode[] data;
//数据长度
int length;
/**
* @Description: 构造函数
* 形参数组的数量需要相一致
* @Param: [paraKeyArray, paraContentArray]
* @return:
*/
public DataArray(int[] paraKeyArray, String[] paraContentArray) {
length = paraKeyArray.length;
data = new DataNode[length];
for (int i = 0; i < length; i++) {
data[i] = new DataNode(paraKeyArray[i], paraContentArray[i]);
}
}
@Override
public String toString() {
String resString = "I am a data array with " + length + " items.\r\n";
for (int i = 0; i < length; i++) {
resString += data[i] + " ";
}
return resString;
}
/**
* @Description: 顺序查找
* 这里是设置第一个空间为哨兵,当到达哨兵的位置即表明未找到元素,查找方式是从后往前
* @Param: [paraKey]
* @return: java.lang.String
*/
public String sequentialSearch(int paraKey) {
data[0].key = paraKey;
int i;
for (i = length - 1; data[i].key != paraKey; i--)
;
return data[i].content;
}
/**
* @Description: 顺序查找测试
* @Param: []
* @return: void
*/
public static void sequentialSearchTest() {
int[] tempUnsortedKeys = {-1, 5, 3, 6, 10, 7, 1, 9};
String[] tempContents = {"The target key is not exist.", "if", "then", "else", "switch", "case", "for", "while"};
DataArray tempDataArray = new DataArray(tempUnsortedKeys, tempContents);
System.out.println(tempDataArray);
System.out.println("Search result of 10 is: " + tempDataArray.sequentialSearch(10));
System.out.println("Search result of 5 is: " + tempDataArray.sequentialSearch(5));
System.out.println("Search result of 4 is: " + tempDataArray.sequentialSearch(4));
}
/**
* @Description: 二分查找
* 前提条件是键值必须为有序
* @Param: [paraKey]
* @return: java.lang.String
*/
public String binarySearch(int paraKey) {
int left = 0;
int right = length - 1;
int mid = (left + right) / 2;
while (left <= right) {
mid = (left + right) / 2;
if (data[mid].key == paraKey) {
return data[mid].content;
} else if (data[mid].key > paraKey) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return "The target key is not exist.";
}
/**
* @Description: 二分查找测试
* @Param: []
* @return: void
*/
public static void binarySearchTest() {
int[] tempSortedKeys = {1, 3, 5, 6, 7, 9, 10};
String[] tempContents = {"if", "then", "else", "switch", "case", "for", "while"};
DataArray tempDataArray = new DataArray(tempSortedKeys, tempContents);
System.out.println(tempDataArray);
System.out.println("Search result of 10 is: " + tempDataArray.binarySearch(10));
System.out.println("Search result of 5 is: " + tempDataArray.binarySearch(5));
System.out.println("Search result of 4 is: " + tempDataArray.binarySearch(4));
}
public static void main(String[] args) {
System.out.println("\r\n-------sequentialSearchTest-------");
sequentialSearchTest();
System.out.println("\r\n-------binarySearchTest-------");
binarySearchTest();
}
}
运行结果:
-------sequentialSearchTest-------
I am a data array with 8 items.
(-1,The target key is not exist.) (5,if) (3,then) (6,else) (10,switch) (7,case) (1,for) (9,while)
Search result of 10 is: switch
Search result of 5 is: if
Search result of 4 is: The target key is not exist.
-------binarySearchTest-------
I am a data array with 7 items.
(1,if) (3,then) (5,else) (6,switch) (7,case) (9,for) (10,while)
Search result of 10 is: while
Search result of 5 is: else
Search result of 4 is: The target key is not exist.
注:
1.顺序查找使用岗哨可以节约一半的时间. 为此, 第 0 个位置不可以放有意义的数据, 即有效数据只有 length - 1 个.
2.顺序查找时间复杂度为 O ( n ) .
3.折半查找时间复杂度为 O ( log n ) .
4.书上为简化起见, 只关注键. 这里使用键值对来表示一条完整的数据. 实际应用中可以把 content 改成任何想要的数据类型.
5.在查找速度方面,顺序查找自然是不及折半查找,从另一方面来说,顺序查找对数据要求不高,无需数据按照某种方式排列,也无需指定存储格式。所以从应用范围来说,顺序查找算法自然会更好。