经典算法掌握

排序算法是对一组数据按照特定规则进行排序的算法。常见的排序算法有冒泡排序、插入排序、选择排序、快速排序和归并排序等。

  1. 冒泡排序(Bubble Sort):
    冒泡排序是通过不断比较相邻的两个元素并交换位置,让较大(或较小)的元素逐渐往后(或往前)移动,直到所有元素都排好序。冒泡排序的时间复杂度是O(n^2),其中n是数组的长度。

    1. 从数组的第一个元素开始,比较它与下一个元素的大小。
    2. 如果当前元素大于下一个元素,则交换它们的位置。
    3. 继续比较下一个元素,重复步骤2,直到比较到倒数第二个元素。
    4. 完成一轮比较后,最大的元素已经被“冒泡”到数组的末尾。
    5. 重复步骤1-4,但是这次只需比较到倒数第三个元素,因为最后两个元素已经是有序的了。
    6. 重复执行步骤1-5,直到所有元素都被排序。
      public static void bubbleSort(int[] arr) {
              int n = arr.length;
              for (int i = 0; i < n - 1; i++) {
                  for (int j = 0; j < n - i - 1; j++) {
                      if (arr[j] > arr[j + 1]) {
                          // 交换arr[j]和arr[j+1]
                          int temp = arr[j];
                          arr[j] = arr[j + 1];
                          arr[j + 1] = temp;
                      }
                  }
              }
          }

  2. 插入排序(Insertion Sort):
    插入排序是将未排序的元素逐个插入已排序的序列中,通过不断比较和交换元素的位置,最终得到一个有序序列。插入排序的时间复杂度为O(n^2),空间复杂度为O(1)。虽然插入排序的时间复杂度比较高,但是在实际应用中,当待排序序列基本有序时,插入排序的性能会比较好。

    1. 从第一个元素开始,该元素可以认为已经被排序。
    2. 取出下一个元素,在已经排序的元素序列中从后向前扫描。
    3. 如果该元素(已排序)大于新元素,将该元素移到下一位置。
    4. 重复步骤3,直到找到已排序的元素小于或等于新元素的位置。
    5. 将新元素插入到该位置后。
    6. 重复步骤2~5,直到所有元素都排序完毕。
      public static void insertionSort(int[] arr) {
              int n = arr.length;
              for (int i = 1; i < n; i++) {
                  int key = arr[i];
                  int j = i - 1;
      
                  while (j >= 0 && arr[j] > key) {
                      arr[j + 1] = arr[j];
                      j--;
                  }
                  arr[j + 1] = key;
              }
          }

  3. 选择排序(Selection Sort):
    选择排序是每次从未排序的元素中找到最小(或最大)的元素,将其放在已排序序列的末尾(或开头),直到所有元素都排好序。选择排序的时间复杂度为O(n^2),其中n为待排序数据的个数。它的优点是实现简单,不需要额外的存储空间,但是由于每次都要遍历剩余的未排序数据,因此效率较低。在实际应用中,选择排序一般适用于数据量较小的情况。

    1. 遍历待排序序列,从第一个元素开始,依次和后面的元素进行比较,找到最小(或最大)的元素。
    2. 将找到的最小(或最大)元素与第一个元素交换位置。
    3. 继续从第二个元素开始遍历,重复步骤1和步骤2,直到所有元素都排好序。
      public class SelectionSort {
          public static void selectionSort(int[] arr) {
              int n = arr.length;
              
              for (int i = 0; i < n-1; i++) {
                  int minIndex = i;
                  for (int j = i+1; j < n; j++) {
                      if (arr[j] < arr[minIndex]) {
                          minIndex = j;
                      }
                  }
                  
                  int temp = arr[minIndex];
                  arr[minIndex] = arr[i];
                  arr[i] = temp;
              }
          }
          
          public static void main(String[] args) {
              int[] arr = {64, 25, 12, 22, 11};
              selectionSort(arr);
              System.out.println("排序后的数组:");
              for (int num : arr) {
                  System.out.print(num + " ");
              }
          }
      }

  4. 快速排序(Quick Sort):
    快速排序是通过选择一个基准元素,将序列分割成左右两部分,使得左边的元素都小于等于基准元素,右边的元素都大于等于基准元素,然后分别对左右两部分进行递归排序。快速排序的时间复杂度为O(nlogn),空间复杂度为O(logn)。它是一种原地排序算法,不需要额外的空间。

    1. 选择一个元素作为基准(pivot)。可以选择数组的第一个元素、最后一个元素或者随机选择一个元素作为基准。

    2. 将数组分为两部分,左边部分包含比基准小的元素,右边部分包含比基准大的元素。

    3. 对左右两部分分别进行递归排序。

    4. 合并左右两部分,即将左边部分的元素、基准元素、右边部分的元素按照顺序组合成一个有序数组。

      public class QuickSort {
          public void quickSort(int[] arr, int low, int high) {
              if (low < high) {
                  int pivotIndex = partition(arr, low, high);
                  quickSort(arr, low, pivotIndex - 1);
                  quickSort(arr, pivotIndex + 1, high);
              }
          }
      
          private int partition(int[] arr, int low, int high) {
              int pivot = arr[high];
              int i = low - 1;
              for (int j = low; j < high; j++) {
                  if (arr[j] <= pivot) {
                      i++;
                      swap(arr, i, j);
                  }
              }
              swap(arr, i + 1, high);
              return i + 1;
          }
      
          private void swap(int[] arr, int i, int j) {
              int temp = arr[i];
              arr[i] = arr[j];
              arr[j] = temp;
          }
      }

  5. 归并排序(Merge Sort):
    归并排序是将序列不断分割成两部分,分别对左右两部分进行递归排序,然后将排好序的左右两部分合并成一个有序序列。归并排序的时间复杂度为O(nlogn),其中n为待排序数组的长度。它是一种稳定的排序算法,适用于各种规模的数据集。但是归并排序需要额外的空间来存储临时数组,空间复杂度为O(n)。

    具体的归并排序算法如下:
    1. 将待排序的数组分割成两个子数组,直到每个子数组只有一个元素。
    2. 递归地对每个子数组进行归并排序。
    3. 将两个有序的子数组合并成一个有序的数组。       

        合并两个有序的子数组的过程如下:

  1.  创建一个临时数组,用于存放合并后的结果。
  2. 定义两个指针,分别指向两个子数组的起始位置。
  3. 比较两个指针指向的元素,将较小的元素放入临时数组中,并将对应指针向后移动一位。
  4. 重复步骤3,直到其中一个子数组的元素全部放入临时数组中。
  5. 将另一个子数组剩余的元素放入临时数组中。
  6. 将临时数组中的元素拷贝回原始数组中。
    public class MergeSort {
        public static void mergeSort(int[] arr) {
            if (arr == null || arr.length <= 1) {
                return;
            }
            
            int[] temp = new int[arr.length];
            mergeSort(arr, 0, arr.length - 1, temp);
        }
        
        private static void mergeSort(int[] arr, int start, int end, int[] temp) {
            if (start >= end) {
                return;
            }
            
            int mid = start + (end - start) / 2;
            mergeSort(arr, start, mid, temp); // 对左半部分进行归并排序
            mergeSort(arr, mid + 1, end, temp); // 对右半部分进行归并排序
            merge(arr, start, mid, end, temp); // 合并左右两个有序数组
        }
        
        private static void merge(int[] arr, int start, int mid, int end, int[] temp) {
            int left = start;
            int right = mid + 1;
            int index = start;
            
            while (left <= mid && right <= end) {
                if (arr[left] <= arr[right]) {
                    temp[index++] = arr[left++];
                } else {
                    temp[index++] = arr[right++];
                }
            }
            
            while (left <= mid) {
                temp[index++] = arr[left++];
            }
            
            while (right <= end) {
                temp[index++] = arr[right++];
            }
            
            for (int i = start; i <= end; i++) {
                arr[i] = temp[i];
            }
        }
        
        public static void main(String[] args) {
            int[] arr = {4, 2, 7, 1, 5, 9};
            mergeSort(arr);
            
            for (int num : arr) {
                System.out.print(num + " ");
            }
        }
    }

以上是对常见排序算法的简单介绍,实际上每种算法都有不同的实现方式和优化方法,可以根据具体问题和数据特点选择合适的算法。

你可能感兴趣的:(算法,排序算法,数据结构)