GO里的排序算法 | 青训营笔记
这是我参与「第三届青训营 -后端场」笔记创作活动的的第4篇笔记
首先总结一下一些常见排序算法的时空复杂度
| 排序算法 | 平均时间复杂度 | 最差时间复杂度 | 空间复杂度 | 数据对象稳定性 |
|---|---|---|---|---|
| 冒泡排序 | O(n2) | O(n2) | O(1) | 稳定 |
| 选择排序 | O(n2) | O(n2) | O(1) | 数组不稳定、链表稳定 |
| 插入排序 | O(n2) | O(n2) | O(1) | 稳定 |
| 快速排序 | O(n*log2n) | O(n2) | O(log2n) | 不稳定 |
| 堆排序 | O(n*log2n) | O(n*log2n) | O(1) | 不稳定 |
| 归并排序 | O(n*log2n) | O(n*log2n) | O(n) | 稳定 |
| 希尔排序 | O(n*log2n) | O(n2) | O(1) | 不稳定 |
| 计数排序 | O(n+m) | O(n+m) | O(n+m) | 稳定 |
| 桶排序 | O(n) | O(n) | O(m) | 稳定 |
| 基数排序 | O(k*n) | O(n2) | 稳定 |
pdqsort(pattern-defeating-quicksort)
这是一种不稳定混合排序算法,针对不同的序列做了优化,使它在不同的情况下都有着不错的性能
- 当处于短序列时(泛型版本为小于等于24的序列),使用插入排序
- 其他情况,使用快速排序来保证整体性能
- 当快排表现不佳时,使用堆排序包俩正最坏情况下时间复杂度O(n*logn)
- 快排的时候,为了保证pivot的选择不在序列两端,会采样好几个元素,选取其中位数作为pivot
各个排序算法的实现
public class test {
public static void main(String[] args) {
long start = System.currentTimeMillis();
int[] nums = new int[100000];
Random random = new Random();
for (int i = 0; i < nums.length; i++) {
nums[i] = random.nextInt(10000);
}
for (int i = 0; i < nums.length; i++) {
System.out.print(nums[i] + " ");
}
System.out.println();
Solution6 solution = new Solution6();
nums = solution.sortArray(nums);
for (int i = 0; i < nums.length; i++) {
System.out.print(nums[i] + " ");
}
System.out.println();
long end = System.currentTimeMillis();
System.out.println(end - start);
}
}
//冒泡排序
//稳定
//时间复杂度O(n2)
//空间复杂度O(1)
class Solution1 {
public int[] sortArray(int[] nums) {
int len = nums.length;
for (int i = 0; i < len - 1; i++) {
for (int j = 0; j < len - i - 1; j++) {
if (nums[j] > nums[j + 1]) {
int temp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = temp;
}
}
}
return nums;
}
}
//选择排序
//稳定
class Solution2 {
public int[] sortArray(int[] nums) {
for (int i = 0; i < nums.length; i++) {
int minIndex = i;
for (int j = i; j < nums.length; j++) {
if (nums[j] < nums[minIndex]) {
minIndex = j;
}
}
int temp = nums[i];
nums[i] = nums[minIndex];
nums[minIndex] = temp;
}
return nums;
}
}
//插入排序
//稳定
class Solution3 {
public int[] sortArray(int[] nums) {
for (int i = 1; i < nums.length; i++) {
for (int j = i; j > 0; j--) {
if (nums[j] < nums[j - 1]) {
int temp = nums[j];
nums[j] = nums[j - 1];
nums[j - 1] = temp;
} else {
break;
}
}
}
return nums;
}
}
//快速排序
//不稳定
class Solution4 {
public int[] sortArray(int[] nums) {
quickSort(nums, 0, nums.length - 1);
return nums;
}
private void quickSort(int[] nums, int low, int high) {
if (low >= high) {
return;
}
int first = low;
int last = high;
int key = nums[first];
while (first < last) {
while (first < last && nums[last] >= key) {
last--;
}
if (first < last) {
nums[first] = nums[last];
first++;
}
while (first < last && nums[first] <= key) {
first++;
}
if (first < last) {
nums[last] = nums[first];
last--;
}
}
nums[first] = key;
quickSort(nums, low, first - 1);
quickSort(nums, first + 1, high);
}
}
//堆排序
//不稳定
class Solution5 {
public int[] sortArray(int[] nums) {
for (int i = (nums.length - 1) / 2; i >= 0; i--) {
adjustHead(nums, i, nums.length);
}
for (int i = nums.length - 1; i > 0; i--) {
int temp = nums[i];
nums[i] = nums[0];
nums[0] = temp;
adjustHead(nums, 0, i);
}
return nums;
}
private void adjustHead(int[] nums, int parent, int length) {
int lChild = parent * 2 + 1;
while (lChild < length) {
int rChild = lChild + 1;
if (rChild < length && nums[rChild] > nums[lChild]) {
lChild = rChild;
}
if (nums[parent] > nums[lChild]) {
break;
} else {
int temp = nums[parent];
nums[parent] = nums[lChild];
nums[lChild] = temp;
}
parent = lChild;
lChild = parent * 2 + 1;
}
}
}
//归并排序
//需要空间O(n)
//稳定
class Solution6 {
public int[] sortArray(int[] nums) {
int[] temp = new int[nums.length];
mergeSort(nums, 0, nums.length - 1, temp);
return nums;
}
private void mergeSort(int[] nums, int left, int right, int[] temp) {
if (left >= right) {
return;
}
int mid = (left + right) / 2;
mergeSort(nums, left, mid, temp);
mergeSort(nums, mid + 1, right,temp);
int a = left;
int b = mid + 1;
int tempIndex = left;
while (a <= mid && b <= right) {
if (nums[a] < nums[b]) {
temp[tempIndex] = nums[a];
tempIndex++;
a++;
} else {
temp[tempIndex] = nums[b];
tempIndex++;
b++;
}
}
while (a <= mid) {
temp[tempIndex] = nums[a];
tempIndex++;
a++;
}
while (b <= right) {
temp[tempIndex] = nums[b];
tempIndex++;
b++;
}
for (int i = left; i <= right; i++) {
nums[i] = temp[i];
}
}
}