Chapter 8 Search Algorithms
- Sequential (linear) lookup
- Binary Search/Half Search
- Interpolation lookup
- fibonacci search
1 Linear Lookup
Code implementation:
public class SeqSearch { public static void main(String[] args) { int arr[] = {1, 9, 11, -1, 34, 89}; int index = seqSearch(arr, 11); if (index == -1 ) { System.out.println("Can't find..."); } else { System.out.println("Found, subscribed as:" + index); } } /** * Here we implement a linear search that finds a value that meets the criteria and returns * @param arr target array * @param value target value * @return Result */ public static int seqSearch(int[] arr, int value) { //Linear search is a one-by-one comparison that returns subscripts when identical values are found for (int i = 0; i < arr.length; i++) { if (arr[i] == value) { return i; } } return -1; } }
2 Binary Search:
- Binary an ordered array to find {1,8, 10, 89, 1000, 1234}. Enter an array to see if the number exists, and find the subscript. If not, prompt "No number".
- After-class thinking: {1,8, 10, 89, 1000, 1000, 1234} How to find all the values when there are multiple identical values in an ordered array, such as 1000 here.
Code implementation:
import java.util.ArrayList; import java.util.Arrays; import java.util.List; //Binary Search (Original + Improvement) [Order before Search] public class BinarySearch { public static void main(String[] args) { //First /* int[] arr = {1, 8, 10, 89, 1000, 1234}; int resIndex = binarySearch(arr, 0, arr.length, 1); System.out.println("The index of this number is: "+ resIndex"; */ //Think questions: int[] arr = {1,8, 10, 89, 1000, 1000, 1000, 1000, 1234}; List<Integer> resIndexList = binarySearch2(arr, 0, arr.length - 1, 1000); System.out.println("resIndexList=" + resIndexList); } //Binary Search /** * @param arr array * @param left Index on the left * @param right Index on the right * @param findVal Value to find * @return Return subscript if found and -1 if not */ public static int binarySearch(int[] arr, int left, int right, int findVal) { //When left > right, the entire array is recursive, but not found if (left > right) { return -1; } int mid = (left + right) / 2; int midVal = arr[mid]; if (findVal > midVal) {//Recursion Right return binarySearch(arr, mid + 1, right, findVal); } else if (findVal < midVal) {//Recursion Left return binarySearch(arr, left, mid - 1, findVal); } else { return mid; } } //Complete a question: /* After-class thinking: {1,8,10,89,1000,1000,1234} When in an ordered array, How to find all the values when there are multiple identical values, such as 1000 here. Idea analysis: 1. Don't return right away when the mid index value is found 2. Scan to the left of the mid index value, adding all subscripts that satisfy 1000 elements to the set ArrayList 3. Scan to the right of the mid index value, adding all subscripts that satisfy 1000 elements to the set ArrayList 4. Return ArrayList */ public static ArrayList<Integer> binarySearch2(int[] arr, int left, int right, int findVal) { //When left > right, the entire array is recursive, but not found if (left > right) { return new ArrayList<Integer>();//That's where you can tell size } int mid = (left + right) / 2; int midVal = arr[mid]; if (findVal > midVal) {//Recursion Right return binarySearch2(arr, mid + 1, right, findVal); } else if (findVal < midVal) {//Recursion Left return binarySearch2(arr, left, mid - 1, findVal); } else { // 1. Don't return immediately after finding the index value of mid // 2. Scan to the left of the mid index value, adding all subscripts that satisfy 1000 elements to the set ArrayList // 3. Scan to the right of the mid index value, adding all subscripts that satisfy 1000 elements to the set ArrayList // 4. Return ArrayList ArrayList<Integer> resIndexList = new ArrayList<Integer>(); //Scan to the left of the mid index value, adding all subscripts that satisfy 1000 elements to the set ArrayList int temp = mid - 1; while (true) { if (temp < 0 || arr[temp] != findVal) {//Sign out break; } //Otherwise, put temp in resIndexList resIndexList.add(temp); temp -= 1;//temp move left } resIndexList.add(mid); //Scan to the right of the mid index value, adding all subscripts that satisfy 1000 elements to the set ArrayList temp = mid + 1; while (true) { if (temp > arr.length - 1 || arr[temp] != findVal) {//Sign out break; } //Otherwise, put temp in resIndexList resIndexList.add(temp); temp += 1;//temp right shift } return resIndexList; } } }
3 Interpolation lookup
Introduction of 2.1 Interpolation Search Principle
- The interpolation lookup algorithm is similar to a binary lookup except that the interpolation lookup starts at the adaptive mid each time.
- The mid index formula in the half search is low for left index, high for right index right.key is the findVal we talked about earlier
- int mid = low + (high - low) * (key - arr[low]) / (arr[high] - arr[low]) ;
/Interpolation Index/
Corresponds to the preceding code formula:
nt mid = left + (right – left) * (findVal – arr[left]) / (arr[right] – arr[left]) - An example of an array of interpolation lookup algorithms 1-100
2.2 Interpolation Finding Application Cases
Interpolate an ordered array to find {1,8,10,89,1000,1234}. Enter an array to see if the number exists, and find the subscript. If not, prompt "No number".
import java.util.Arrays; //Interpolation algorithms are useful when data is compact public class InsertValueSearch { public static void main(String[] args) { int[] arr = new int[100]; for (int i = 0; i < arr.length; i++) { arr[i] = i + 1; } //System.out.println(Arrays.toString(arr)); int index1 = insertValueSearch(arr, 0, arr.length - 1, 100); int index2 = binarySearch(arr, 0, arr.length - 1, 100); System.out.println("The index of the number you are looking for is:" + index1); } //Write interpolation lookup algorithm //Interpolation lookup algorithms require arrays to be ordered as well /** * * @param arr target array * @param left Leftmost Index * @param right Right most index * @param findVal Value to find * @return Returns the index of the result to be found */ public static int insertValueSearch(int[] arr, int left, int right, int findVal) { System.out.println("Interpolation looked up once."); //Judging ahead of time (optimizing code), and secondly, if not connected, the array may be out of bounds if ( left > right || findVal < arr[0] || findVal > arr[arr.length - 1]) { return -1; } //Find mid, adaptive writing int mid = left + (right - left) * (findVal - arr[left]) / (arr[right] - arr[left]); int midVal = arr[mid]; if (findVal > midVal) {//Indicates to recurse to the right return insertValueSearch(arr, mid + 1, right, findVal); } else if (findVal < midVal) {//Explain recursive search to the left return insertValueSearch(arr, left, mid -1, findVal); } else { return mid; } } public static int binarySearch(int[] arr, int left, int right, int findVal) { System.out.println("Binary search once."); //When left > right, the entire array is recursive, but not found if (left > right) { return -1; } int mid = (left + right) / 2; int midVal = arr[mid]; if (findVal > midVal) {//Recursion Right return binarySearch(arr, mid + 1, right, findVal); } else if (findVal < midVal) {//Recursion Left return binarySearch(arr, left, mid - 1, findVal); } else { return mid; } } }
2.3 Notes on Interpolation Finding
Interpolation lookup considerations:
- Interpolation is faster for lookup tables with large amount of data and uniform keyword distribution.
- This method is not necessarily better than half-search when keywords are not evenly distributed
3 Fibonacci (Golden Section) search algorithm
3.1 Introduction to Fibonacci (Golden Section) Search:
- Golden section is the division of a line into two parts so that the ratio of one part to the length equals the ratio of the other part to the part. The approximate value of the first three digits is 0.618. Because the shape designed at this ratio is so beautiful, it is called the golden section, also known as the Chinese-foreign ratio. This is a magical number with little intent.
- The Fibonacci sequence {1, 1, 2, 3, 5, 8, 13, 21, 34, 55} finds that the ratio of two neighbors of the Fibonacci sequence is infinitely close to the golden section value of 0.618
3.2 Fibonacci (Golden Section) Principle:
The Fibonacci search principle is similar to the first two, except that the position of the intermediate node (mid) is changed. Instead of being intermediate or interpolated, mid is located near the golden section point, which is mid=low+F(k-1)-1 (F stands for the Fibonacci sequence), as shown in the following figure:
Understanding of F(k-1)-1:
-
From the properties of the Fibonacci number column F[k]=F[k-1]+F[k-2], you can get (F[k]-1) =(F[k-1]-1) +(F[k-2]-1)+1. This formula shows that if the length of the sequence table is F[k]-1, it can be divided into two segments, F[k-1]-1 and F[k-2]-1, as shown in the figure above. Thus the middle position is mid=low+F(k-1)-1.
-
Similarly, each subparagraph can be split in the same way
However, the length of the order table n does not necessarily equal F[k]-1, so you need to increase the original order table length n to F[k]-1. Where the k-value can make F[k]-1 exactly greater than or equal to n, it is obtained from the following code. As the order table length increases, the new position (from n+1 to F[k]-1) is assigned to the value of n position.
3.3 Fibonacci Find Application Cases
Find {1,8, 10, 89, 1000, 1234} for an ordered array, enter an array to see if it exists, and find the subscript. If not, prompt "No number".
Code implementation:
//Fibonacci algorithm import java.util.Arrays; //In fact, the Fibonacci column is the index value of the array, which is arranged according to the Fibonacci column. public class FibonacciSearch { public static int maxSize = 20; public static void main(String[] args) { int[] arr = {1, 8, 10, 89, 1000, 1234}; System.out.println("index = " + fibSearch(arr, 1));//0 } //The latter formula, mid = low + F(k - 1) - 1, requires the use of the Fibonacci sequence. So we need to get a Fibonacci sequence first //We use a non-recursive method to get a Fibonacci sequence public static int[] fib() { int[] f = new int[maxSize]; f[0] = 1; f[1] = 1; for (int i = 2; i < maxSize; i++) { f[i] = f[i - 1] + f[i - 2]; } return f; } //Writing the Fibonacci algorithm /** * * @param a array * @param key The keys we need to find * @return Returns the corresponding subscript if there is no -1 */ public static int fibSearch(int[] a, int key) { int low = 0; int high = a.length - 1; int k = 0;//Subscript representing the Fibonacci split value int mid = 0;//Store mid value int[] f = fib();//Get the Fibonacci series //Gets the subscript of the Fibonacci split value while (high > f[k] - 1) {//This condition holds, indicating that it was not found k++; } //Because f[k] may be longer than a because we need to use the Arrays class to construct a new array and point to temp[] //Insufficient parts will be filled with 0 int[] temp = Arrays.copyOf(a, f[k]); //You actually need to fill temp with the last number of a arrays //Give an example: //temp = {1, 8, 10, 89, 1000, 1234, 0, 0, 0}; => {1, 8, 10, 89, 1000, 1234, 1234, 1234, 1234}; for (int i = high + 1; i < temp.length; i++) { temp[i] = a[high]; } //Use while for sequential processing to find our key while (low <= high) {//As long as this condition is met, you can find mid = low + f[k - 1] - 1; if (key < temp[mid]) {//We should continue to look to the left high = mid - 1; //Why k-- //Explain: //1.All Elements = Previous Element + Subsequent Element //2. f[k] = f[k - 1] + f[k - 2]; //Because there are f[k-1] elements in front of it, you can continue to split f[k-1] = f[k-2] + f[k-3] //That is, continue looking for K before f[k-1]-- //That is, mid = f[k - 1 - 1] - 1 on the next loop k--; } else if (key < temp[mid]) { low = mid + 1; //Why k-= 2 //Explain: //1.All Elements = Previous Element + Subsequent Element //2. f[k] = f[k - 1] + f[k - 2]; //3.Because we have f[k-2] behind us, we can continue to split f[k-1] = f[k-3] + f[k-4] //4.Find k -= 2 in front of f[k-2] //5.That is, the next loop mid = f[k - 1 - 2] - 1 k -= 2; } else {//Eureka //Need to determine which subscript to return if (mid <= high) { return mid; } else { return high; } } } return -1; } }