一、顺序查找
顺序查找又称为线性查找,是一种最简单的查找方法。适用于线性表的顺序存储结构和链式存储结构。
基本思路 从第一个元素m开始逐个与需要查找的元素x进行比较,当比较到元素值相同(即m=x)时返回元素m的下标,如果比较到最后都没有找到,则返回-1。 复杂度分析 查找成功时的平均查找长度为: ASL = 每个元素被查找的概率 * 总的元素的个数=1/n*(1+2+3+…+n) = (n+1)/2 ; 当查找不成功时,需要n+1次比较,时间复杂度为O(n),所以,顺序查找的时间复杂度为O(n)。 优缺点 缺点:是当n 很大时,平均查找长度较大,效率低; 优点:是对表中数据元素的存储没有要求。另外,对于线性链表,只能进行顺序查找。
public static int sequentialSearch(int[] array, int target) {
for (int i = 0; i < array.length; i++) {
if (array[i] == target) {
return i;
}
}
return -1;
}
二、二分查找
迭代法示例代码如下
static int binarySearch1(int arr[],int len,int target){
/*初始化左右搜索边界*/
int left=0,right=len-1;
int mid;
while(left<=right){
/*中间位置:两边界元素之和/2向下取整*/
mid=(left+right)/2;
/*arr[mid]大于target,即要寻找的元素在左半边,所以需要设定右边界为mid-1,搜索左半边*/
if(target<arr[mid]){
right=mid-1;
/*arr[mid]小于target,即要寻找的元素在右半边,所以需要设定左边界为mid+1,搜索右半边*/
}else if(target>arr[mid]){
left=mid+1;
/*搜索到对应元素*/
}else if(target==arr[mid]){
return mid;
}
}
/*搜索不到返回-1*/
return -1;
}
递归法示例代码如下:
static int binarySearch2(int array[],int left,int right,int target){
if(left<=right){
int mid=(left+right)/2;
/*搜索到对应元素*/
if(array[mid]==target){
return mid;
}else if(array[mid]<target){
/*array[mid]小于target,即要寻找的元素在右半边,所以需要设定左边界为mid+1,搜索右半边*/
return binarySearch2(array,mid+1,right,target);
}else{
/*array[mid]大于target,即要寻找的元素在左半边,所以需要设定右边界为mid-1,搜索左半边*/
return binarySearch2(array,left,mid-1,target);
}
}else{
return -1;
}
}
三、插值查找
迭代法插值查找示例代码如下:
private static int insertSearch1(int arr[],int target){
/*初始化左右搜索边界*/
int left=0,right=arr.length-1;
int mid;
while(left<=right){
mid=left+(target-arr[left])/(arr[right]-arr[left])*(right-left);
/*arr[mid]大于target,即要寻找的元素在左半边,所以需要设定右边界为mid-1,搜索左半边*/
if(target<arr[mid]){
right=mid-1;
/*arr[mid]小于target,即要寻找的元素在右半边,所以需要设定左边界为mid+1,搜索右半边*/
}else if(target>arr[mid]){
left=mid+1;
/*搜索到对应元素*/
}else if(target==arr[mid]){
return mid;
}
}
/*搜索不到返回-1*/
return -1;
}
递归法插值查找示例代码如下:
private static int insertSearch2(int array[],int left,int right,int target){
if(left<=right){
int mid=left+(target-array[left])/(array[right]-array[left])*(right-left);
/*搜索到对应元素*/
if(array[mid]==target){
return mid;
}else if(array[mid]<target){
/*array[mid]小于target,即要寻找的元素在右半边,所以需要设定左边界为mid+1,搜索右半边*/
return insertSearch2(array,mid+1,right,target);
}else{
/*array[mid]大于target,即要寻找的元素在左半边,所以需要设定右边界为mid-1,搜索左半边*/
return insertSearch2(array,left,mid-1,target);
}
}else{
return -1;
}
}
四、斐波那契查找
public class FibonacciSearch {
public static int FLENGTH = 20;
public static void main(String[] args) {
int [] arr = {1,8,10,89,100,134};
int target = 89;
System.out.println("目标元素在数组中位置是:" + fibSearch(arr, target));
}
public static int[] fib() {
int[] f = new int[FLENGTH];
f[0] = 1;
f[1] = 1;
for (int i = 2; i < FLENGTH; i++) {
f[i] = f[i-1] + f[i-2];
}
return f;
}
public static int fibSearch(int[] arr, int target) {
int low = 0;
int high = arr.length - 1;
int k = 0;
int mid = 0;
int f[] = fib();
/*获取最相邻的斐波那契数组中元素的值,该值略大于数组的长度*/
while(high > f[k] - 1) {
k++;
}
/*因为 f[k]值可能大于arr的长度。如果大于时,需要构造一个新的数组temp[],将arr数组中的元素拷贝过去,不足的部分会使用0填充*/
int[] temp=Arrays.copyOf(arr, f[k]);
/*然后将temp后面填充的0,替换为最后一位数字
*如将temp数组由{1,8,10,89,100,134,0,0}变换为{1,8,10,89,100,134,134,134}*/
for(int i = high + 1; i < temp.length; i++) {
temp[i] = arr[high];
}
while (low <= high) {
mid = low + f[k - 1] - 1;
if(target < temp[mid]) {
high = mid - 1;
/*因为f[k]=f[k-1]+f[k-2],所以k--就相当于取temp数组的左边部分*/
k--;
} else if ( target > temp[mid]) {
low = mid + 1;
/*同理,f[k]=f[k-1]+f[k-2],k -= 2就相当于取temp数组的右边部分*/
k -= 2;
} else {
/*原arr数组中的值*/
if(mid <= high){
return mid;
/*在temp中,扩展出来的高位的值*/
}else{
return high;
}
}
}
return -1;
}
}
五、树表查找
public class BinarySortTree {
public static void main(String[] args) {
int[] array = {35,76,6,22,16,49,49,98,46,9,40};
BinaryTree root = new BinaryTree(array[0]);
for(int i = 1; i < array.length; i++){
createBST(root, array[i]);
}
System.out.println("中序遍历结果:");
midOrderPrint(root);
System.out.println();
searchBST(root, 22, null);
searchBST(root, 100, null);
}
/*创建二叉排序树*/
public static void createBST(BinaryTree root, int element){
BinaryTree newNode = new BinaryTree(element);
if(element > root.value){
if(root.right == null)
root.right = newNode;
else
createBST(root.right, element);
}else if(element < root.value){
if(root.left == null)
root.left = newNode;
else
createBST(root.left, element);
}else{
System.out.println("该节点" + element + "已存在");
return;
}
}
/*二叉树中查找元素*/
public static void searchBST(BinaryTree root, int target, BinaryTree p){
if(root == null){
System.out.println("查找"+target+"失败");
}else if(root.value == target){
System.out.println("查找"+target+"成功");
}else if(root.value >= target){
searchBST(root.left, target, root);
}else{
searchBST(root.right, target, root);
}
}
/*二叉树的中序遍历*/
public static void midOrderPrint(BinaryTree rt){
if(rt != null){
midOrderPrint(rt.left);
System.out.print(rt.value + " ");
midOrderPrint(rt.right);
}
}
}
六、分块查找
public class BlockSearch {
/*主表*/
static int[] valueList = new int[]{
104, 101, 103, 105,102, 0, 0, 0, 0, 0,
201, 202, 204, 203,0, 0, 0, 0, 0, 0,
303, 301, 302, 0, 0, 0, 0, 0, 0, 0
};
/*索引表*/
static Block[] indexList = new Block[]{
new Block(1, 0, 5),
new Block(2, 10, 4),
new Block(3, 20, 3)
};
public static void main(String[] args) {
System.out.println("原始主表:");
printElemts(valueList);
/*分块查找*/
int searchValue = 203;
System.out.println("元素"+searchValue+",在列表中的索引为:"+blockSearch(searchValue)+"\n");
/*插入数据并查找*/
int insertValue = 106;
/*插入成功,查找插入位置*/
if (insertBlock(insertValue)) {
System.out.println("插入元素"+insertValue+"后的主表:");
printElemts(valueList);
System.out.println("元素" + insertValue + "在列表中的索引为:" + blockSearch(insertValue));
}
}
public static void printElemts(int[] array) {
for(int i = 0; i < array.length; i++){
System.out.print(array[i]+" ");
if ((i+1)%10 == 0) {
System.out.println();
}
}
}
/*插入数据*/
public static boolean insertBlock(int key) {
Block item = null;
/*确定插入到哪个块中,在该例子中,第一个block中放的是100-200之间的数,第二个block中放的是200-300之间的数,以此类推*/
int index = key/100;
int i = 0;
/*找到对应的block*/
for (i = 0; i < indexList.length; i++) {
if (indexList[i].index == index) {
item = indexList[i];
break;
}
}
/*如果数组中不存在对应的块,则不能插入该数据*/
if (item == null) {
return false;
}
/*将元素插入到每个块的最后*/
valueList[item.start + item.length] = key;
/*更新该块的长度*/
indexList[i].length++;
return true;
}
public static int blockSearch(int key) {
Block indexItem = null;
/*确定插入到哪个块中,在该例子中,第一个block中放的是100-200之间的数,第二个block中放的是200-300之间的数,以此类推*/
int index = key/100;
/*找到对应的block*/
for(int i = 0;i < indexList.length; i++) {
if(indexList[i].index == index) {
indexItem = indexList[i];
break;
}
}
/*如果数组中不存在对应的块,则返回-1,查找失败*/
if(indexItem == null)
return -1;
/*在对应的block中查找*/
for(int i = indexItem.start; i < indexItem.start + indexItem.length; i++) {
if(valueList[i] == key)
return i;
}
return -1;
}
}
七、哈希查找
public class HashSearch {
/*待查找序列*/
static int[] array = {13, 29, 27, 28, 26, 30, 38};
/* 初始化哈希表长度,此处哈希表容量设置的和array长度一样。
* 其实正常情况下,哈希表长度应该要长于array长度,因为使用
* 开放地址法时,可能会多使用一些空位置
*/
static int hashLength = 7;
static int[] hashTable = new int[hashLength];
public static void main(String[] args) {
/*将元素插入到哈希表中*/
for (int i = 0; i < array.length; i++) {
insertHashTable(hashTable, array[i]);
}
System.out.println("哈希表中的数据:");
printHashTable(hashTable);
int data = 28;
System.out.println("\n要查找的数据"+data);
int result = searchHashTable(hashTable, data);
if (result == -1) {
System.out.println("对不起,没有找到!");
} else {
System.out.println("在哈希表中的位置是:" + result);
}
}
/*将元素插入到哈希表中*/
public static void insertHashTable(int[] hashTable, int target) {
int hashAddress = hash(hashTable, target);
/*如果不为0,则说明发生冲突*/
while (hashTable[hashAddress] != 0) {
/*利用开放定址法解决冲突,即向后寻找新地址*/
hashAddress = (++hashAddress) % hashTable.length;
}
/*将元素插入到哈希表中*/
hashTable[hashAddress] = target;
}
public static int searchHashTable(int[] hashTable, int target) {
int hashAddress = hash(hashTable, target);
while (hashTable[hashAddress] != target) {
/*寻找原始地址后面的位置*/
hashAddress = (++hashAddress) % hashTable.length;
/*查找到开放单元(未存放元素的位置)或 循环回到原点,表示查找失败*/
if (hashTable[hashAddress] == 0 || hashAddress == hash(hashTable, target)) {
return -1;
}
}
return hashAddress;
}
/*用除留余数法计算要插入元素的地址*/
public static int hash(int[] hashTable, int data) {
return data % hashTable.length;
}
public static void printHashTable(int[] hashTable) {
for(int i=0;i<hashTable.length;i++)
System.out.print(hashTable[i]+" ");
}
}