一、查找算法
1. 基本查找
- 基本查找也叫顺序查找。
- 核心:从0索引开始挨个往后查找。
a. 示例
- import java.util.ArrayList;
- public class Demo2 {
- public static void main(String[] args) {
- int[] arr = {131, 127, 147, 81, 103, 23, 7, 79, 81};
- System.out.println(searchNumber(arr, 81));
- }
- public static ArrayList<Integer> searchNumber(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. 二分查找
- 二分查找又称折半查找。
- 前提条件:数组中的数据必须是有序的。
- 如果数据是乱的,必须先排序。
- 只能确定当前key在数组中是否存在,不能确定其索引值。
- 核心:每次清除一半的查找范围。
- 过程:
- 界说min和max表示当前要查找的范围
- 界说中心索引mid(min和max中心的索引)
- 如果key在mid的左边,缩小范围时,min稳定,max等于mid减1
- 如果key在mid的右边,缩小范围时,max稳定,min等于mid加1
a. 示例
- public class Demo3 {
- public static void main(String[] args) {
- int[] arr = {7, 23, 79, 81, 103, 127, 131, 147};
- System.out.println(BinarySearch(arr, 127));
- }
- public static int BinarySearch(int[] arr, int number){
- // 定义范围
- int min = 0;
- int max = arr.length;
- while (true) {
- if (min > max) {
- return -1;
- }
- // 定义中间索引
- int mid = (min + max) / 2;
- // 核心代码
- if (arr[mid] > number) {
- max = mid - 1;
- } else if (arr[mid] < number) {
- min = mid + 1;
- } else if (arr[mid] == number) {
- return mid;
- }
- }
- }
- }
复制代码
3. 插值查找
- 插值查找在二分查找的底子上改进。
- 前提条件:数据尽可能的分布匀称。
- 核心: m i d = m i n + k e y − a r r [ m i n ] a r r [ m a x ] − a r r [ m i n ] × ( m a x − m i n ) mid = min + \dfrac{key-arr[min]}{arr[max]-arr[min]}\times(max-min) mid=min+arr[max]−arr[min]key−arr[min]×(max−min)
- mid值是key在数组中的百分比位置。
- mid = 偏移量 + 左隔断 ÷ 总隔断 × (最大值-最小值)
4. 斐波那契查找
- 斐波那契查找在二分查找的底子上改进。
- 根据黄金分割点来盘算mid索引。
- mid = min + 黄金分割点左半边长度 - 1。
5. 分块查找
- 原则
- 前一块中的最大数据,小于后一块中所有的数据(块内无序,块间有序)
- 块数数量一般等于元素个数开根号。比如:16个元素一般分为4块左右。
- 核心:先确定要查找的元素在哪一块,然后再块内挨个查找。
a. 示例
- 界说一个数组 {16, 5, 9, 12, 21, 18, 32, 23, 37, 26, 45, 34, 50, 48, 61, 52, 73, 66},查询数字是否在数组中。
- package day18.search;
- public class Demo4 {
- 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};
- int number = 66;
- // 现确定在哪一块
- int index = getIndex(blockArr, arr, number);
- // 在块中查找
- System.out.println(index);
- }
- private static int getIndex(Block[] blockArr, int[] arr, int number) {
- int indexBlock = findIndexBlock(blockArr, number);
- if (indexBlock == -1) {
- return -1;
- }
- int startIndex = blockArr[indexBlock].getStartIndex();
- int endIndex = blockArr[indexBlock].getEndIndex();
- for (int i = startIndex; i <= endIndex; i++) {
- if (arr[i] == number) {
- return i;
- }
- }
- return -1;
- }
- public static int findIndexBlock(Block[] blockArr, int number){
- for (int i = 0; i < blockArr.length; i++) {
- if (number <= 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;
- }
- public int getMax() {
- return max;
- }
- public void setMax(int max) {
- this.max = max;
- }
- public int getStartIndex() {
- return startIndex;
- }
- public void setStartIndex(int startIndex) {
- this.startIndex = startIndex;
- }
- public int getEndIndex() {
- return endIndex;
- }
- public void setEndIndex(int endIndex) {
- this.endIndex = endIndex;
- }
- }
复制代码
二、排序算法
1. 冒泡排序
- 步骤:
- 相邻的元素两两比较,大的放反面,小的放前面;
- 第一轮比较完毕之后,最大值就已经确定,第二轮可以少循环一次,反面以此类推;
- 如果数组中有n个数据,总共要实行n-1轮。
a. 示例
- 界说一个数组{2, 1, 4, 5, 3},并排序。
- import java.util.Arrays;
- public class Demo1 {
- public static void main(String[] args) {
- int[] arr = {2, 1, 4, 5, 3};
- // 循环多少轮
- 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;
- }
- }
- }
- System.out.println(Arrays.toString(arr));
- }
- }
复制代码
2. 选择排序
- 步骤:
- 从0索引开始,与每一个索引上的元素依次比较。
- 小的放前面,大的放反面。
a. 示例
- 界说一个数组{2, 1, 6, 8, 3},并排序。
- import java.util.Arrays;
- public class Demo2 {
- public static void main(String[] args) {
- int[] arr = {2, 1, 6, 8, 3};
- // 进行比较的索引值
- for (int i = 0; i < arr.length; i++) {
- // 拿每个索引值对应的元素与后面的每个元素进行比较
- // 每完成一轮,索引值加1
- 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;
- }
- }
- }
- System.out.println(Arrays.toString(arr));
- }
- }
复制代码
3、插入排序
- 步骤:
- 将索引在[0, N]的元素看作有序的,把[N+1, arr.length-1]的元素当成无序的。
- 遍历无序的数据,将遍历到的元素插入到有序序列中适当的位置,如遇到相同数据,插在反面。
- N的范围:0~arr.length-1
a. 示例
- 界说数组:{3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48}
- import java.util.Arrays;
- public class Demo3 {
- public static void main(String[] args) {
- int[] arr = {3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48};
- // 找到无序的那一组数据从哪个索引开始
- int startIndex = -1;
- for (int i = 0; i < arr.length; i++) {
- if (arr[i] > arr[i + 1]) {
- startIndex = i + 1;
- break;
- }
- }
- // 遍历从startIndex开始到最后一个元素
- 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--;
- }
- }
- System.out.println(Arrays.toString(arr));
- }
- }
复制代码
4. 快速排序(效率最高)
- 步骤:
- 将排序范围内的第一个数字作为基准数,在界说两个索引变量start、end
- 索引start从前往后找比基准数大的,索引end从后往前找比基准数小的。
- start、end都找到一个数后,替换两个数。
- 循环上面三步,直到start和end指向同一个索引。让基准数与这个索引的元素替换(基准数归位)。
- 归位后的效果:基准数左边的,比基准数小;基准数右边的,比基准数大。
- 对基准数两边的数据重复上面四步,直到要求范围的开始索引大于竣事索引。
a. 示例
- 界说一个长度为100万的数组,为数组随机添补数字,给数组举行排序。
- import java.util.Random;
- public class Demo6 {
- public static void main(String[] args) {
- Random random = new Random();
- int[] arr = new int[1000000];
- for (int i = 0; i < arr.length; i++) {
- arr[i] = random.nextInt();
- }
-
- long start = System.currentTimeMillis();
- quickSort(arr, 0, arr.length - 1);
- long end = System.currentTimeMillis();
- System.out.println("共用时: " + (end-start));
- }
- public static void quickSort(int[] arr, int startIndex, int endIndex) {
- if (startIndex > endIndex) return;
- // 记录索引值,防止被修改
- int start = startIndex;
- int end = endIndex;
- // 记录基准数
- int baseNumber = arr[startIndex];
- // 利用循环找到要交换的数
- while (start != end) {
- // 从end往前找
- while (end > start && arr[end] >= baseNumber) end--;
- // 从start往后找
- while (end > start && arr[start] <= baseNumber) start++;
- // 交换start和end
- int temp = arr[end];
- arr[end] = arr[start];
- arr[start] = temp;
- }
- // 基准数归位
- int temp = arr[startIndex];
- arr[startIndex] = arr[end];
- arr[end] = temp;
- // 确定6左边的范围
- quickSort(arr, startIndex, start - 1);
- // 确定6右边的范围
- quickSort(arr, end + 1, endIndex);
- }
- }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |