递归

写递归代码最关键的是写出递推公式,找到终止条件,剩下将递推公式转化为代码就很简单了

排序

图片.png

  • 冒泡排序

图片.png

  1. // 冒泡排序,a表示数组,n表示数组大小
  2. public void bubbleSort(int[] a, int n) {
  3. if (n <= 1) return;
  4. for (int i = 0; i < n; ++i) {
  5. // 提前退出冒泡循环的标志位
  6. boolean flag = false;
  7. for (int j = 0; j < n - i - 1; ++j) {
  8. if (a[j] > a[j+1]) { // 交换
  9. int tmp = a[j];
  10. a[j] = a[j+1];
  11. a[j+1] = tmp;
  12. flag = true; // 表示有数据交换
  13. }
  14. }
  15. if (!flag) break; // 没有数据交换,提前退出
  16. }
  17. }
  • 插入排序

将数组中的数据分为两个区间,已排序区间和未排序区间。初始已排序区间只有一个元素,就是数组的第一个元素。插入算法的核心思想是取未排序区间中的元素,在已排序区间中找到合适的插入位置将其插入,并保证已排序区间数据一直有序。重复这个过程,直到未排序区间中元素为空,算法结束
图片.png

  1. // 插入排序,a表示数组,n表示数组大小
  2. public void insertionSort(int[] a, int n) {
  3. if (n <= 1) return;
  4. for (int i = 1; i < n; ++i) {
  5. int value = a[i];
  6. int j = i - 1;
  7. // 查找插入的位置
  8. for (; j >= 0; --j) {
  9. if (a[j] > value) {
  10. a[j+1] = a[j]; // 数据移动
  11. } else {
  12. break;
  13. }
  14. }
  15. a[j+1] = value; // 插入数据
  16. }
  17. }
  • 选择排序

图片.png
插入排序也包含两种操作,一种是元素的比较,一种是元素的移动。当我们需要将一个数据 a 插入到已排序区间时,需要拿 a 与已排序区间的元素依次比较大小,找到合适的插入位置。找到插入点之后,我们还需要将插入点之后的元素顺序往后移动一位,这样才能腾出位置给元素 a 插入。
📢
原地排序:就是特指空间复杂度是 O(1) 的排序算法
O(1)空间复杂度:除了存储数据本身的空间不需要额外的辅助存储空间

  • 归并排序

图片.png
图片.png

  • 快速排序

图片.png
图片.png
图片.png

  • 线性排序:桶排序、计数排序、基数排序,这三个算法是非基于比较的排序算法,都不涉及元素之间的比较操作

桶排序
图片.png