排序算法
排序算法
下面是对比较类排序算法的详细介绍:
-
冒泡排序(Bubble Sort):
-
原理:通过重复遍历待排序的数列,比较每对相邻元素,如果它们的顺序错误就把它们交换过来。遍历数列的工作是重复进行的,直到没有再需要交换的元素,这意味着该数列已经排序完成。
-
时间复杂度:平均和最坏情况下都是 O(n2)O(n2),最好情况是 O(n)O(n)(当输入数组已经是有序的)。
-
空间复杂度:O(1)O(1),因为它只需要一个额外的存储空间。
-
代码实现:
public class BubbleSort { 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]) { // swap arr[j] and arr[j+1] int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } } public static void main(String[] args) { int[] arr = {64, 34, 25, 12, 22, 11, 90}; bubbleSort(arr); System.out.println("Sorted array: "); for (int i : arr) { System.out.print(i + " "); } } }
-
-
选择排序(Selection Sort):
-
原理:首先在未排序序列中找到最小(或最大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(或最大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
-
时间复杂度:无论最好、最坏和平均情况都是 O(n2)O(n2)。
-
空间复杂度:O(1)O(1)。
-
代码实现:
public class SelectionSort { public static void selectionSort(int[] arr) { int n = arr.length; for (int i = 0; i < n - 1; i++) { int min_idx = i; for (int j = i + 1; j < n; j++) { if (arr[j] < arr[min_idx]) { min_idx = j; } } // swap arr[i] and arr[min_idx] int temp = arr[min_idx]; arr[min_idx] = arr[i]; arr[i] = temp; } } public static void main(String[] args) { int[] arr = {64, 25, 12, 22, 11}; selectionSort(arr); System.out.println("Sorted array: "); for (int i : arr) { System.out.print(i + " "); } } }
-
-
插入排序(Insertion Sort):
-
原理:构建有序序列,对未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到 O(1)O(1) 的额外空间的排序)。
-
时间复杂度:平均和最坏情况下都是 O(n2)O(n2),最好情况是 O(n)O(n)(当输入数组已经是有序的)。
-
空间复杂度:O(1)O(1)。
-
代码实现:
public class InsertionSort { 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 = j - 1; } arr[j + 1] = key; } } public static void main(String[] args) { int[] arr = {12, 11, 13, 5, 6}; insertionSort(arr); System.out.println("Sorted array: "); for (int i : arr) { System.out.print(i + " "); } } }
-
-
希尔排序(Shell Sort):
-
原理:也称递减增量排序算法,是插入排序的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因DL.Shell于1959年提出而得名。希尔排序是把记录按不同的步长分组,对每组使用直接插入排序算法排序;随着步长逐渐缩小,整个序列基本有序,最后进行一次直接插入排序算法。
-
时间复杂度:平均情况 O(nlogn)O(nlogn) 到 O(n2)O(n2),取决于步长序列的选择。
-
空间复杂度:O(1)O(1)。
-
代码实现:
public class ShellSort { public static void shellSort(int[] arr) { int n = arr.length; for (int gap = n / 2; gap > 0; gap /= 2) { for (int i = gap; i < n; i += 1) { int temp = arr[i]; int j; for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) arr[j] = arr[j - gap]; arr[j] = temp; } } } public static void main(String[] args) { int[] arr = {12, 34, 54, 2, 3}; shellSort(arr); System.out.println("Sorted array: "); for (int i : arr) { System.out.print(i + " "); } } }
-
-
归并排序(Merge Sort):
-
原理:采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。
-
时间复杂度:无论最好、最坏和平均情况都是 O(nlogn)O(nlogn)。
-
空间复杂度:O(n)O(n),因为需要额外的空间来存储合并后的数组。
-
代码实现:
public class MergeSort { public static void mergeSort(int[] arr) { mergeSort(arr, 0, arr.length - 1); } private static void mergeSort(int[] arr, int l, int r) { if (l < r) { int m = (l + r) / 2; mergeSort(arr, l, m); mergeSort(arr, m + 1, r); merge(arr, l, m, r); } } private static void merge(int[] arr, int l, int m, int r) { int n1 = m - l + 1; int n2 = r - m; int[] L = new int[n1]; int[] R = new int[n2]; for (int i = 0; i < n1; ++i) L[i] = arr[l + i]; for (int j = 0; j < n2; ++j) R[j] = arr[m + 1 + j]; int i = 0, j = 0; int k = l; while (i < n1 && j < n2) { if (L[i] <= R[j]) { arr[k] = L[i]; i++; } else { arr[k] = R[j]; j++; } k++; } while (i < n1) { arr[k] = L[i]; i++; k++; } while (j < n2) { arr[k] = R[j]; j++; k++; } } public static void main(String[] args) { int[] arr = {12, 11, 13, 5, 6}; mergeSort(arr); System.out.println("Sorted array: "); for (int i : arr) { System.out.print(i + " "); } } }
-
-
快速排序(Quick Sort):
-
原理:通过一个基准值将数据分为两部分,其中一部分的所有数据都比另外一部分的所有数据要小,然后再递归地对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以达到整个数据变成有序序列。
-
时间复杂度:平均情况 O(nlogn)O(nlogn),最坏情况 O(n2)O(n2)(当数据已经是有序或逆序时)。
-
空间复杂度:O(logn)O(log**n),递归栈的深度。
-
代码实现:
public class QuickSort { public static void quickSort(int[] arr, int low, int high) { if (low < high) { int pi = partition(arr, low, high); quickSort(arr, low, pi - 1); quickSort(arr, pi + 1, high); } } private static 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++; int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } int temp = arr[i + 1]; arr[i + 1] = arr[high]; arr[high] = temp; return i + 1; } public static void main(String[] args) { int[] arr = {10, 7, 8, 9, 1, 5}; quickSort(arr, 0, arr.length - 1); System.out.println("Sorted array: "); for (int i : arr) { System.out.print(i + " "); } } }
-
-
堆排序(Heap Sort):
-
原理:利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子节点的键值或索引总是小于(或者大于)它的父节点。
-
时间复杂度:无论最好、最坏和平均情况都是 O(nlogn)O(nlogn)。
-
空间复杂度:O(1)O(1),因为堆是原地排序。
-
代码实现:
public class HeapSort { public static void heapSort(int[] arr) { int n = arr.length; for (int i = n / 2 - 1; i >= 0; i--) heapify(arr, n, i); for (int i = n - 1; i >= 0; i--) { int temp = arr[0]; arr[0] = arr[i]; arr[i] = temp; heapify(arr, i, 0); } } private static void heapify(int[] arr, int n, int i) { int largest = i; int l = 2 * i + 1; int r = 2 * i + 2; if (l < n && arr[l] > arr[largest]) largest = l; if (r < n && arr[r] > arr[largest]) largest = r; if (largest != i) { int swap = arr[i]; arr[i] = arr[largest]; arr[largest] = swap; heapify(arr, n, largest); } } public static void main(String[] args) { int[] arr = {12, 11, 13, 5, 6, 7}; heapSort(arr); System.out.println("Sorted array: "); for (int i : arr) { System.out.print(i + " "); } } }
-
排序算法比较
| 排序算法 | 时间复杂度 (平均) | 时间复杂度 (最坏) | 时间复杂度 (最好) | 空间复杂度 | 稳定性 | 备注 |
|---|---|---|---|---|---|---|
| 冒泡排序 | O(n^2) | O(n^2) | O(n) | O(1) | 不稳定 | 简单但效率低 |
| 选择排序 | O(n^2) | O(n^2) | O(n^2) | O(1) | 不稳定 | 简单但效率低 |
| 插入排序 | O(n^2) | O(n^2) | O(n) | O(1) | 稳定 | 对小数据集或基本有序的数据集效率高 |
| 希尔排序 | O(nlogn) | O(n^2) | O(nlogn) | O(1) | 不稳定 | 效率比简单插入排序高,但不如快速排序和归并排序 |
| 归并排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(n) | 稳定 | 高效率,需要额外空间 |
| 快速排序 | O(nlogn) | O(n^2) | O(nlogn) | O(logn) | 不稳定 | 高效率,但最坏情况下效率低 |
| 堆排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(1) | 不稳定 | 可以原地排序,但构建堆的过程可能较慢 |
这些算法中,归并排序和堆排序是稳定的排序算法,而快速排序和冒泡排序、选择排序、插入排序、希尔排序是不稳定的排序算法。稳定性指的是相等的元素在排序过程中不会改变它们的先后顺序。
浙公网安备 33010602011771号