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); }
-
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?