赞
踩
排序算法的重要性不言而喻,为了加深对这十种算法的理解,固写此文。
十大经典排序算法 | 平均时间复杂度 | 最好时间复杂度 | 最坏时间复杂度 | 空间复杂度 | 排序方式 | 稳定性 |
---|---|---|---|---|---|---|
冒泡排序 | O \Omicron O(n2) | O \Omicron O(n) | O \Omicron O(n2) | O \Omicron O(1) | In-place | 稳定 |
选择排序 | O \Omicron O(n2) | O \Omicron O(n2) | O \Omicron O(n2) | O \Omicron O(1) | In-place | 不稳定 |
插入排序 | O \Omicron O(n2) | O \Omicron O(n) | O \Omicron O(n2) | O \Omicron O(1) | In-place | 稳定 |
希尔排序 | O \Omicron O(n1.3) | O \Omicron O(n) | O \Omicron O(n2) | O \Omicron O(1) | In-place | 不稳定 |
归并排序 | O \Omicron O(n log \log log2n) | O \Omicron O(n log \log log2n) | O \Omicron O(n log \log log2n) | O \Omicron O(n) | Out-place | 稳定 |
快速排序 | O \Omicron O(n log \log log2n) | O \Omicron O(n log \log log2n) | O \Omicron O(n2) | O \Omicron O( log \log log2n) | In-place | 不稳定 |
堆排序 | O \Omicron O(n log \log log2n) | O \Omicron O(n log \log log2n) | O \Omicron O(n log \log log2n) | O \Omicron O(1) | In-place | 不稳定 |
计数排序 | O \Omicron O(n+k) | O \Omicron O(n+k) | O \Omicron O(n+k) | O \Omicron O(k) | Out-place | 稳定 |
桶排序 | O \Omicron O(n+k) | O \Omicron O(n+k) | O \Omicron O(n2) | O \Omicron O(n+k) | Out-place | 稳定 |
基数排序 | O \Omicron O(n*k) | O \Omicron O(n*k) | O \Omicron O(n*k) | O \Omicron O(n+k) | Out-place | 稳定 |
表中数据说明: |
该十种排序算法可分为如下所示的两大类
算法步驟
代码实现
public class BubbleSort { public static void bubbleSort(int[] arr) { int len = arr.length; for (int i = 0; i < len - 1; i++) { boolean flag = true; for (int j = 0; j < len - i - 1; j++) { if (arr[j] > arr[j + 1]) { int tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; flag = false; } } if (flag) { break; } } } }
算法步驟
代码实现
public class SelectionSort { public static void selectionSort(int[] arr) { int len = arr.length; for (int i = 0; i < len - 1; i++) { int minVal = i; for (int j = i + 1; j < len; j++) { if (arr[minVal] > arr[j]) { minVal = j; } } if (minVal != i) { int tmp = arr[i]; arr[i] = arr[minVal]; arr[minVal] = tmp; } } } }
算法步驟
代码实现
public class InsertionSort {
public static void insertionSort(int[] arr) {
for (int i = 1; i < arr.length; i++) {
int val = arr[i], j = i;
while (j > 0 && val < arr[j - 1]) {
arr[j] = arr[j - 1];
j--;
}
arr[j] = val;
}
}
}
算法步驟
其中,增量gap=length/2,缩小增量继续以gap = gap/2的方式,这种增量选择我们可以用一个序列来表示,{n/2, (n/2)/2, …, 1},称为增量序列。一般的增量序列都选择以上说明的这个,但不一定是最优的。
代码实现
public class ShellSort { public static void shellSort(int[] arr) { int len = arr.length, tmp, j; for (int gap = len / 2; gap >= 1; gap = gap / 2) { for (int i = gap; i < len; i++) { tmp = arr[i]; j = i - gap; while (j >= 0 && arr[j] > tmp) { arr[j + gap] = arr[j]; j -= gap; } arr[j + gap] = tmp; } } } }
算法步驟
代码实现
import java.util.Arrays; public class MergeSort { public static int[] mergeSort(int[] arr) { int len = arr.length; if (len < 2) { return arr; } int mIdx = len / 2; return merge(mergeSort(Arrays.copyOfRange(arr, 0, mIdx)), mergeSort(Arrays.copyOfRange(arr, mIdx, len))); } private static int[] merge(int[] arrLeft, int[] arrRight) { int leftLen = arrLeft.length, rightLen = arrRight.length, leftIdx = 0, rightIdx = 0, idx = 0; int[] result = new int[leftLen + rightLen]; while (leftIdx < leftLen && rightIdx < rightLen) { if (arrLeft[leftIdx] < arrRight[rightIdx]) { result[idx++] = arrLeft[leftIdx++]; } else { result[idx++] = arrRight[rightIdx++]; } } while (leftIdx < leftLen) { result[idx++] = arrLeft[leftIdx++]; } while (rightIdx < rightLen) { result[idx++] = arrRight[rightIdx++]; } return result; } }
算法步驟
代码实现
public class QuickSort { public static void quickSort(int[] arr) { sort(arr, 0, arr.length - 1); } private static void sort(int[] arr, int left, int right) { if (left < right) { int pivotIdx = partition(arr, left, right); sort(arr, 0, pivotIdx - 1); sort(arr, pivotIdx + 1, right); } } private static int partition(int[] arr, int left, int right) { int idx = left + 1; for (int i = idx; i <= right; i++) { if (arr[left] > arr[i]) { swap(arr, i, idx++); } } swap(arr, left, idx - 1); return idx - 1; } private static void swap(int[] arr, int idx1, int idx2) { int tmp = arr[idx1]; arr[idx1] = arr[idx2]; arr[idx2] = tmp; } }
算法步驟
代码实现
public class HeapSort { private static int heapLen; public static void heapSort(int[] arr) { heapLen = arr.length; for (int i = heapLen - 1; i >= 0; i--) { heapify(arr, i); } for (int i = heapLen - 1; i > 0; i--) { swap(arr, 0, heapLen - 1); heapLen--; heapify(arr, 0); } } private static void heapify(int[] arr, int idx) { int left = idx * 2 + 1, right = idx * 2 + 2, largest = idx; if (left < heapLen && arr[left] > arr[largest]) { largest = left; } if (right < heapLen && arr[right] > arr[largest]) { largest = right; } if (largest != idx) { swap(arr, largest, idx); heapify(arr, largest); } } private static void swap(int[] arr, int idx1, int idx2) { int tmp = arr[idx1]; arr[idx1] = arr[idx2]; arr[idx2] = tmp; } }
算法步驟
代码实现
public class CountingSort { public static void countingSort(int[] arr) { int len = arr.length; if (len < 2) return; int minVal = arr[0], maxVal = arr[0]; for (int i = 1; i < len; i++) { if (arr[i] < minVal) { minVal = arr[i]; } else if (arr[i] > maxVal) { maxVal = arr[i]; } } int[] countArr = new int[maxVal - minVal + 1]; for (int val : arr) { countArr[val - minVal]++; } for (int arrIdx = 0, countIdx = 0; countIdx < countArr.length; countIdx++) { while (countArr[countIdx]-- > 0) { arr[arrIdx++] = minVal + countIdx; } } } }
算法步驟
代码实现
import java.util.ArrayList; import java.util.List; public class BucketSort { private static List<Integer> bucketSort(List<Integer> arr, int bucketSize) { int len = arr.size(); if (len < 2 || bucketSize == 0) { return arr; } int minVal = arr.get(0), maxVal = arr.get(0); for (int i = 1; i < len; i++) { if (arr.get(i) < minVal) { minVal = arr.get(i); } else if (arr.get(i) > maxVal) { maxVal = arr.get(i); } } int bucketNum = (maxVal - minVal) / bucketSize + 1; List<List<Integer>> bucket = new ArrayList<>(); for (int i = 0; i < bucketNum; i++) { bucket.add(new ArrayList<>()); } for (int val : arr) { int idx = (val - minVal) / bucketSize; bucket.get(idx).add(val); } for (int i = 0; i < bucketNum; i++) { if (bucket.get(i).size() > 1) { bucket.set(i, bucketSort(bucket.get(i), bucketSize / 2)); } } List<Integer> result = new ArrayList<>(); for (List<Integer> val : bucket) { result.addAll(val); } return result; } }
算法步骤
import java.util.ArrayList; import java.util.List; //基数排序 public class RadixSort { public static void radixSort(int[] arr) { if (arr.length < 2) return; int maxVal = arr[0];//求出最大值 for (int a : arr) { if (maxVal < a) { maxVal = a; } } int n = 1; while (maxVal / 10 != 0) {//求出最大值位数 maxVal /= 10; n++; } for (int i = 0; i < n; i++) { List<List<Integer>> radix = new ArrayList<>(); for (int j = 0; j < 10; j++) { radix.add(new ArrayList<>()); } int index; for (int a : arr) { index = (a / (int) Math.pow(10, i)) % 10; radix.get(index).add(a); } index = 0; for (List<Integer> list : radix) { for (int a : list) { arr[index++] = a; } } } } }
数据量规模较小,考虑插入或选择。当元素分布有序时插入将大大减少比较和移动记录的次数,如果不要求稳定性,可以使用选择,效率略高于插入;
数据量规模中等,使用希尔排序;
数据量规模较大,考虑堆排序(元素分布接近正序或逆序)、快速排序(元素分布随机)和归并排序(稳定性);
一般来说不使用冒泡。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。