GO里的排序算法 | 青训营笔记

150 阅读2分钟

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];
        }
​
    }
}