Java基础学习(十一):常见算法
- Java基础学习(十一):常见算法
- 查找算法
- 排序算法
本文为个人学习记录,内容学习自 黑马程序员
查找算法
-
七大查找算法:基本查找(顺序查找)、二分查找(折半查找)、插值查找、斐波那契查找、分块查找、数表查找、哈希查找
-
基本查找
-
核心:从 0 索引开始挨个往后查找
-
示例:使用基本查找,在数组中查询某个元素存不存在
public static boolean basicSearch(int[] arr, int target) {for (int i = 0; i < arr.length; i++) {if (arr[i] == target) {return true;}}return false; }
-
-
二分查找
-
前提:数组中的数据必须是有序的
-
核心:每次排除一半的查找范围
-
示例:使用二分查找,在数组中查询某个元素存不存在
public static boolean binarySearch(int[] arr, int target) {int min = 0;int max = arr.length - 1;while (true) {if (min > max) {return false;}int mid = (min + max) / 2;if (arr[mid] > target) {max = mid - 1;} else if (arr[mid] < target) {min = mid + 1;} else {return true;}} }
-
-
插值查找
-
插值查找是对于二分查找的改进,当然,只有在数组中数据分布比较均匀时才有改进效果
-
核心:计算中间值时不是根据二分,而是通过插值公式
-
-
斐波那契查找
- 斐波那契查找也是对于二分查找的改进
- 核心:计算中间值时不是根据二分,而是根据斐波那契数列进行分割
-
分块查找
-
分块原则:1. 数组中,前一块中的最大数据应小于后一块中的所有数据 2. 块的数量一般等于数字总个数开根号
-
核心:先确定要查找的元素在哪一块,然后在块内挨个查找
-
示例:使用分块查找,在数组中查询某个元素存不存在
public class Test {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[] blocks = {b1, b2, b3};int target = 30;boolean result = BlockSearch(blocks, arr, target);System.out.println(result);}// 分块查找public static boolean BlockSearch(Block[] blocks, int[] arr, int target) {int blockIndex = -1;for (int i = 0; i < blocks.length; i++) {if (target <= blocks[i].getMax()) {blockIndex = i;break;}}if (blockIndex == -1) {return false;}int startIndex = blocks[blockIndex].getStartIndex();int endIndex = blocks[blockIndex].getEndIndex();for (int i = startIndex; i <= endIndex; i++) {if (arr[i] == target) {return true;}}return false;} }// 块类,存储每一块的最大值、起始索引和结束索引 class Block {private int max;private int startIndex;private int endIndex;// 省略构造方法和get/set方法 }
-
扩展的分块查找:考虑到有时会面临无法从小到大分块的情况,扩展后的分块查找只要求各个块的数值区间不发生重合即可
-
排序算法
-
十大排序算法:冒泡排序、选择排序、插入排序、快速排序、希尔排序、堆排序、桶排序、归并排序、计数排序、基数排序
-
冒泡排序
-
核心:相邻的数据两两比较,小的放前面,大的放后面,每轮排序都会将最大值后置
-
说明:假如有 4 个数字,第 1 轮时依次比较 1 和 2,2 和 3,3 和 4;第 2 轮时依次比较 1 和 2,2 和 3;第 3 轮时比较 1 和 2
-
示例:使用冒泡排序对数组从小到大排序
int[] arr = {2, 4, 5, 3, 1}; 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;}} }
-
-
选择排序
-
核心:从 0 索引开始,拿每一个索引上的元素和后面的元素依次比较,小的放前面,大的放后面,每轮排序都会将最小值前置
-
说明:假如有 4 个数字,第 1 轮时依次比较 1 和 2,1 和 3,1 和 4;第 2 轮时依次比较 2 和 3,2 和 4;第 3 轮时比较 3 和 4
-
示例:使用选择排序对数组从小到大排序
int[] arr = {2, 4, 5, 3, 1}; for (int i = 0; i < arr.length - 1; 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;}} }
-
-
插入排序
-
核心:将 0 索引的元素到 N 索引的元素看作是有序的,将 N+1 索引的元素到最后一个元素看作是无序的。遍历无序的数据将之插入到有序序列中的对应位置,如果遇到相同的数据则插在后面
-
示例:使用插入排序对数组从小到大排序
int[] arr = {2, 4, 5, 3, 1}; // 1.计算无序序列的开始索引 startIndex int startIndex = -1; for (int i = 0; i < arr.length; i++) {if (arr[i] > arr[i + 1]) {startIndex = i + 1;break;} } // 2.遍历无序序列,插入到有序序列中 for (int i = startIndex; 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--;} }
-
-
快速排序
-
核心:第一轮排序时,将 0 索引的数作为基准数,确定基准数在数组中正确的位置,比基准数小的全部在左边,比基准数大的全部在右边;第二轮时,根据归位后的基准数将数组分成两个小数组,在这两个小数组中继续进行快速排序
-
优势:利用递归的思想,效率非常高
-
示例:使用快速排序对数组从小到大排序
public static void main(String[] args) {int[] arr = {2, 4, 5, 3, 1};quickSort(arr, 0, arr.length - 1); }// 快速排序 // 参数一:要排序的数组 // 参数二:排序的起始索引 // 参数二:排序的结束索引 public static void quickSort(int[] arr, int i, int j) {// 记录要排序的范围int start = i;int end = j;// 递归结束条件if (start > end) {return;}// 记录基准数int baseNumber = arr[i];while (start != end) {// 必须先移动end再移动start!// 利用end从后往前查找比基准数小的数字while (true) {if (end <= start || arr[end] < baseNumber) {break;}end--;}// 利用start从前往后查找比基准数大的数字while (true) {if (end <= start || arr[start] > baseNumber) {break;}start++;}// 将end和start指向的数字交换int temp = arr[start];arr[start] = arr[end];arr[end] = temp;}// 基准数归位int temp = arr[i];arr[i] = arr[start];arr[start] = temp;// 对归位后基准数左侧的小数组进行快速排序quickSort(arr, i, start - 1);// 对归位后基准数右侧的小数组进行快速排序quickSort(arr, start + 1, j); }
-