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);
      }
      
posted @   victoria6013  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示