在本文中我将介绍Java中的常见算法,查找算法包括基本查找、二分查找、插值查找和分块查找。排序算法包括冒泡排序、选择排序、插入排序和快速排序
查找算法:
1.基本查找:
代码:
public class BasicSearchDemo {public static void main(String[] args) {int[] arr = {1,21,31,41,51,61,71,81};Scanner sc = new Scanner(System.in);String numStr = sc.nextLine();int num = Integer.parseInt(numStr);boolean result = basicSearch(arr, num);System.out.println(result);}//基本查找方法public static boolean basicSearch(int[] arr, int number) {for (int i = 0; i < arr.length; i++) {if(arr[i] == number) {return true;}}return false;}
}
这是简单的基本查找,通过遍历数组来查看元素是否存在
运行结果:
基本查找小练习:
代码(含题目要求):
public class BasicSearchTest {public static void main(String[] args) {/*练习1:需求:定义一个方法利用基本查找,查询某个元素在数组中的索引要求:不需要考虑数组中元素是否重复*//*练习2:需求:定义一个方法利用基本查找,查询某个元素在数组中的索引要求:需要考虑数组中元素有重复的可能性例如:{1,1,1,2,3,4,5,6,1}若查找1,则需要返回所有元素1的索引,即0,1,2,8*///生成一个数组int[] arr = {1,11,21,31,41,51,51,61,51,61};//键盘录入一个元素Scanner sc = new Scanner(System.in);System.out.println("请输入您要查找的元素:");String numStr = sc.nextLine();int num = Integer.parseInt(numStr);System.out.println(getIndex(arr, num));System.out.println(getAllIndex(arr, num));}//练习1public static int getIndex(int[] arr, int number) {for (int i = 0; i < arr.length; i++) {if(arr[i] == number) {return i;}}return -1;}//练习2public static ArrayList<Integer> getAllIndex(int[] arr, int number) {ArrayList<Integer> list = new ArrayList<>();for (int i = 0; i < arr.length; i++) {if(arr[i] == number) {list.add(i);}}return list;}
}
运行结果:
2.二分查找:
特点:
二分查找的数据必须是按大小顺序排好的二分查找可以很大的提高查找效率
代码:
public class BinarySearchDemo1 {public static void main(String[] args) {//二分查找的数据必须是按大小顺序排好的//二分查找可以很大的提高查找效率//定义数组int[] arr = {1,21,31,41,51,61,71,81};//键盘录入一个要查找的元素System.out.println("输入要查找的元素:");Scanner sc = new Scanner(System.in);String numStr = sc.nextLine();int num = Integer.parseInt(numStr);System.out.println(binarySearch(arr, num));}//定义二分查找方法public static int binarySearch(int[] arr, int num) {//用min和max表示当前查找范围int min = 0;int max = arr.length - 1;while (true) {//这种情况说明元素不存在if(min > max) {return -1;}//定义中间指针int mid = (min + max) / 2;//进行判断if(arr[mid] < num) {//元素在右边min = mid + 1;} else if(arr[mid] > num) {//元素在左边max = mid - 1;} else {//找到了return mid;}}}
}
3.插值查找:
改变mid位置时使用数学公式使其更靠近要查找的元素
特点:
适用于数据分布较均匀的情况下
代码:
public class InterpolationSearch {public static void main(String[] args) {//适用于数据分布较均匀的情况下int[] arr = {1,2,3,5,6,8,9,10};System.out.println("请输入要查找的元素值:");Scanner sc = new Scanner(System.in);String numStr = sc.nextLine();int num = Integer.parseInt(numStr);int index = interpolationSearch(arr, num);System.out.println(index);}public static int interpolationSearch(int[] arr, int num) {//定义查找范围int min = 0;int max = arr.length - 1;while(true) {if(min > max) {return -1;}//mid = min + (key - arr[min]) / (arr[max] - arr[min]) * (max - min)int mid = min + (num - arr[min]) / (arr[max] - arr[min]) * (max - min);if(arr[mid] > num) {max = mid - 1;} else if(arr[mid] < num) {min = mid + 1;} else {return mid;}}}
}
4.分块查找:
对数据先进行分块,通过先确定要查找的元素属于哪个块,再只需对那个块进行遍历
代码:
public class BlockSearch {public static void main(String[] args) {//注意分块的块数跟元素个数的开方差不多即可//前一块所有元素都小于后一块中的任意元素int[] arr = {16, 5, 9, 12, 21, 18,32, 23, 37, 26, 45, 34,50, 48, 61, 52, 73, 66};//分块Block b1 = new Block(21, 0, 5);Block b2 = new Block(45, 6, 11);Block b3 = new Block(73, 12, 17);//用数组存储Block[] blockArr = {b1,b2,b3};//输入要查找的元素Scanner sc = new Scanner(System.in);System.out.println("请输入要查找的元素");String numStr = sc.nextLine();int num = Integer.parseInt(numStr);int index = getIndex(arr, blockArr, num);System.out.println(index);}private static int getIndex(int[] arr, Block[] blockArr, int num) {int blockIndex = getBlock(blockArr, num);if(blockIndex == -1) {return -1;}//将范围缩小到这块的开始和结束索引int startIndex = blockArr[blockIndex].getStartIndex();int endIndex = blockArr[blockIndex].getEndIndex();//遍历for (int i = startIndex; i <= endIndex; i++) {if(arr[i] == num) {return i;}}return -1;}private static int getBlock(Block[] blockArr, int num) {for (int i = 0; i < blockArr.length; i++) {if(num < blockArr[i].getMax()) {return i;}}return -1;}}class Block {private int max;private int startIndex;private int endIndex;public Block() {}public Block(int max, int startIndex, int endIndex) {this.max = max;this.startIndex = startIndex;this.endIndex = endIndex;}/*** 获取* @return max*/public int getMax() {return max;}/*** 设置* @param max*/public void setMax(int max) {this.max = max;}/*** 获取* @return startIndex*/public int getStartIndex() {return startIndex;}/*** 设置* @param startIndex*/public void setStartIndex(int startIndex) {this.startIndex = startIndex;}/*** 获取* @return endIndex*/public int getEndIndex() {return endIndex;}/*** 设置* @param endIndex*/public void setEndIndex(int endIndex) {this.endIndex = endIndex;}public String toString() {return "Block{max = " + max + ", startIndex = " + startIndex + ", endIndex = " + endIndex + "}";}
}
排序算法:
1.冒泡排序:
特点:
相邻的元素两两比较,大的放右边,小的放左边(从小到大情况)第一轮比较完毕之后,最大值就已经确定,第二轮可以少循环一次,后面以此类推如果数组中有n个数据,那总共执行n-1轮代码就可以
代码:
public class BubbleSort {public static void main(String[] args) {//相邻的元素两两比较,大的放右边,小的放左边(从小到大情况)//第一轮比较完毕之后,最大值就已经确定,第二轮可以少循环一次,后面以此类推//如果数组中有n个数据,那总共执行n-1轮代码就可以//创建一个数组int[] arr = {1,4,5,2,3,9,5,6};int[] resultArr = bubbleSort(arr);for (int i = 0; i < resultArr.length; i++) {System.out.println(resultArr[i]);}}private static int[] bubbleSort(int[] arr) {//外循环:要进行几轮for (int i = 0; i < arr.length - 1; i++) {//内循环:这一轮需要判断几组数据是否应该交换for (int j = 0; j < arr.length - 1 - i; j++) {if(arr[j] > arr[j + 1]) {int temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}return arr;}
}
2.选择排序:
特点:
从0索引开始,拿着每一个索引上的元素跟后面的元素依次比较小的放前面,大的放后面(从小到大情况),以此类推第一轮循环结束后,最小的数据已经确定第二轮循环从1索引开始,以此类推
代码:
public class SelectionSort {public static void main(String[] args) {//从0索引开始,拿着每一个索引上的元素跟后面的元素依次比较//小的放前面,大的放后面(从小到大情况),以此类推//第一轮循环结束后,最小的数据已经确定//第二轮循环从1索引开始,以此类推//创建数组int[] arr = {4,3,9,5,6,8,2,1};int[] resultArr = bubbleSort(arr);for (int i = 0; i < resultArr.length; i++) {System.out.println(resultArr[i]);}}public static int[] bubbleSort(int[] arr) {//外循环:表示几轮for (int i = 0; i < arr.length - 1; i++) {//内循环:i后面的所有数据与i进行比较for (int j = i + 1; j < arr.length; j++) {if(arr[i] > arr[j]) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}}return arr;}
}
3.插入排序:
特点:
将0索引的元素到N索引的元素看做是有序的,把N+1索引的元素到最后一个元素当成是无序的。遍历无序的数据,将遍历到的元素插入有序序列中适当的位置,如遇到相同数据,插在后面。
代码:
public class InsertionSort {public static void main(String[] args) {//将0索引的元素到N索引的元素看做是有序的,把N+1索引的元素到最后一个元素当成是无序的。//遍历无序的数据,将遍历到的元素插入有序序列中适当的位置,如遇到相同数据,插在后面。//创建数组int[] arr = {1,6,5,3,9,7,16,1,22,3};int[] resultArr = insertionSort(arr);for (int i = 0; i < resultArr.length; i++) {System.out.println(resultArr[i]);}}public static int[] insertionSort(int[] arr) {//判断有序元素个数int index = 0;for (int i = 1; i < arr.length; i++) {if(arr[index] < arr[index + 1]) {index++;} else {break;}}//index为最后一个有序元素的索引//有序元素后面的每个元素要插入有序元素中 插入后有序元素加1 索引也++//我的其他思路 复杂了。。/*for (; index < arr.length - 1; index++) {int i = index + 1;for(int j = index; j >= 0; j--) {if(arr[i] >= arr[j]) {break;} else {//有序元素后面的无序元素只要比前面的小就交换位置int temp = arr[i];arr[i] = arr[j];arr[j] = temp;i--;continue;}}}*///从有序数组后的第一个元素到最后一个元素for (int i = index + 1; i < arr.length; i++) {int j = i;while (j > 0 && arr[j] <arr[j - 1]) {int temp = arr[j];arr[j] = arr[j - 1];arr[j - 1] = temp;j--;}}return arr;}
}
4.快速排序
这里展示快速排序之前要先学会递归思想,我先来放两个递归思想的小练习
递归练习一 题目及代码:
public class RecursionAlgorithmTest1 {public static void main(String[] args) {//核心:找出口 找规律//方法中再次调用方法时,参数应更接近出口//求1~100所有整数的和int sum = getSum(100);System.out.println(sum);}//1~100所有整数的和 = 100 + 1~99的和//1~99的和 = 99 + 1~98的和//…………public static int getSum(int num) {//出口if(num == 1) {return 1;}return num + getSum(num - 1);}
}
递归练习二 题目及代码:
public class RecursionAlgorithmTest2 {public static void main(String[] args) {//需求:用递归求5的阶乘,并把结果在控制台输出int factorail = getFactorail(5);System.out.println(factorail);}//5的阶乘 = 5 * 4的阶乘//4的阶乘 = 4 * 3的阶乘//…………public static int getFactorail(int num) {//出口if(num == 1) {return 1;}return num * getFactorail(num - 1);}
}
接下来开始讲解快速排序:
过程:
//将排序范围中的第一个数字作为基准数,在定义两个变量start,end //start从前往后找比基准数大的,end从后往前找比基准数小的。 /*找到之后交换start和end指向的元素,并循环这一过程,直到start和end处于同一个位置, 该位置是基准数在数组中应存入的位置,再让基准数归位*/ //归为后的效果:基准数左边的都比基准数小,右边的都比基准数大
代码演示:
public class QuickSort {public static void main(String[] args) {//创建数组int[] arr = {6,2,3,1,7,5,8};int start = 0;int end = arr.length - 1;quickSort(arr, start, end);for (int i = 0; i < arr.length; i++) {System.out.println(arr[i]);}}private static void quickSort(int[] arr, int i, int j) {//出口if(i >= j) {return;}int start = i;int end = j;//基准数int baseNumber = arr[i];while(start != end) {//end从右往左开始找比基准数小的数while(true) {if(end <= start || arr[end] < baseNumber) {break;}end--;}//start从左往右开始找比基准数大的数while(true) {if(end <= start || arr[start] > baseNumber) {break;}start++;}//交换位置int temp = arr[end];arr[end] = arr[start];arr[start] = temp;}//将基准数与当前start和end索引所在位置交换int temp = arr[i];arr[i] = arr[start];arr[start] = temp;//基准数左边继续重复刚才所做的事quickSort(arr, i, start - 1);//基准数右边继续重复刚才所做的事quickSort(arr, start + 1, j);}
}