[算法] 排序

排序算法有很多种类,可以从时空复杂度、稳定性等角度来分析。

排序算法 平均时间复杂度 最坏时间复杂度 最好时间复杂度 空间复杂度 稳定性
快速排序 O(nlogn) O(n2) O(nlogn) O(logn) 不稳定
冒泡排序 O(n2) O(n2) O(n) O(1) 稳定
归并排序 O(nlogn) O(nlogn) O(nlogn) O(n) 稳定
选择排序 O(n2) O(n2) O(n2) O(1) 不稳定
堆排序 O(nlogn) O(nlogn) O(nlogn) O(1) 不稳定
插入排序 O(n2) O(n2) O(n) O(1) 稳定
希尔排序 O(n1.3) O(n2) O(n) O(1) 不稳定
计数排序 O(n+k) O(n+k) O(n+k) O(k) 稳定
桶排序 O(n) O(n2) O(n) O(n+b) 稳定
基数排序 O(nd) O(nd) O(nd) O(n) 稳定

1. 快速排序

class Solution {
private:
    int partition(vector<int> &nums, int lo, int hi) {
        swap(nums[lo], nums[lo + rand() % (hi - lo + 1)]);
        int pivot = nums[lo];
        while (lo < hi) {
            while (lo < hi && pivot <= nums[hi])
                --hi;
            nums[lo] = nums[hi];
            while (lo < hi && nums[lo] <= pivot)
                ++lo;
            nums[hi] = nums[lo];
        }
        nums[lo] = pivot;
        return lo;
    }

    void quickSort(vector<int> &nums, int lo, int hi) {
        if (lo >= hi)
            return;
        int mi = partition(nums, lo, hi);
        quickSort(nums, lo, mi - 1);
        quickSort(nums, mi + 1, hi);
    }
public:
    vector<int> sortArray(vector<int>& nums) {
        int n = nums.size();
        quickSort(nums, 0, n - 1);
        return nums;
    }
};

2. 冒泡排序

class Solution {
private:
    void bubbleSort(vector<int> &nums) {
        int n = nums.size();
        for (int i = n; i >= 2; --i) {
            bool noSwap = true;
            for (int j = 0; j < i - 1; ++j) {
                if (nums[j] > nums[j + 1]) {
                    swap(nums[j], nums[j + 1]);
                    noSwap = false;
                }
            }
            if (noSwap)
                break;
        }
    }
public:
    vector<int> sortArray(vector<int>& nums) {
        bubbleSort(nums);
        return nums;
    }
};

3. 归并排序

class Solution {
private:
    void merge(vector<int> &nums, int lo, int mi, int hi) {
        vector<int> temp(hi - lo);
        int i = lo, j = mi, k = 0;
        while (i < mi && j < hi) {
            if (nums[i] <= nums[j])
                temp[k++] = nums[i++];
            else
                temp[k++] = nums[j++];
        }
        while (i < mi)
            temp[k++] = nums[i++];
        while (j < hi)
            temp[k++] = nums[j++];
        for (i = lo, k = 0; i < hi; ++i, ++k)
            nums[i] = temp[k];
    }

    void mergeSort(vector<int> &nums, int lo, int hi) {
        if (lo + 1 >= hi)
            return;
        int mi = (lo + hi) / 2;
        mergeSort(nums, lo, mi);
        mergeSort(nums, mi, hi);
        merge(nums, lo, mi, hi);
    }
public:
    vector<int> sortArray(vector<int>& nums) {
        int n = nums.size();
        mergeSort(nums, 0, n);
        return nums;
    }
};

4. 选择排序

class Solution {
private:
    void selectionSort(vector<int> &nums) {
        int n = nums.size();
        for (int i = n; i >= 2; --i) {
            int maxIdx = 0;
            for (int j = 0; j < i; ++j)
                if (nums[j] > nums[maxIdx])
                    maxIdx = j;
            swap(nums[maxIdx], nums[i-1]);
        }
    }
public:
    vector<int> sortArray(vector<int>& nums) {
        selectionSort(nums);
        return nums;
    }
};

5. 堆排序

class Solution {
private:
    void siftDown(vector<int> &nums, int start, int end) {
        int parent = start;
        int child = parent * 2 + 1;
        while (child <= end) {
            if (child + 1 <= end && nums[child] < nums[child + 1])
                ++child;
            if (nums[parent] >= nums[child])
                return;
            swap(nums[parent], nums[child]);
            parent = child;
            child = parent * 2 + 1;
        }
    }

    void heapSort(vector<int> &nums) {
        int n = nums.size();
        for (int i = (n - 2) / 2; i >= 0; --i)
            siftDown(nums, i, n - 1);
        for (int i = n - 1; i >= 0; --i) {
            swap(nums[0], nums[i]);
            siftDown(nums, 0, i - 1);
        }
    }
public:
    vector<int> sortArray(vector<int>& nums) {
        heapSort(nums);
        return nums;
    }
};

6. 插入排序

class Solution {
private:
    void insertionSort(vector<int> &nums) {
        int n = nums.size();
        for (int i = 1; i < n; ++i) {
            int target = nums[i], j = i - 1;
            while (j >= 0 && target < nums[j]) {
                nums[j + 1] = nums[j];
                --j;
            }
            nums[j + 1] = target;
        }
    }
public:
    vector<int> sortArray(vector<int>& nums) {
        insertionSort(nums);
        return nums;
    }
};

7. 希尔排序

class Solution {
private:
    void shellSort(vector<int> &nums) {
        int n = nums.size();
        for (int gap = n / 2; gap >= 1; gap /= 2) {
            for (int i = 0; i < gap; ++i) {
                for (int j = i + gap; j < n; j += gap) {
                    int target = nums[j], k = j - gap;
                    while (k >= 0 && target < nums[k]) {
                        nums[k + gap] = nums[k];
                        k -= gap;
                    }
                    nums[k + gap] = target;
                }
            }
        }
    }
public:
    vector<int> sortArray(vector<int>& nums) {
        shellSort(nums);
        return nums;
    }
};

8. 计数排序

class Solution {
private:
    void countingSort(vector<int> &nums, int minVal, int maxVal) {
        vector<short> count(maxVal - minVal + 1, 0);
        for (int &num : nums)
            count[num - minVal] += 1;
        int idx = 0;
        for (int i = minVal; i <= maxVal; ++i) {
            while (count[i - minVal] > 0) {
                nums[idx++] = i;
                count[i - minVal] -= 1; 
            }
        }
    }
public:
    vector<int> sortArray(vector<int>& nums) {
        countingSort(nums, -50000, 50000);
        return nums;
    }
};

9. 桶排序

class Solution {
private:
    void bucketSort(vector<int> &nums, int minVal, int maxVal) {
        int n = nums.size();
        int bucketNum = (maxVal - minVal) / n + 1;
        vector<vector<int> > buckets(bucketNum, vector<int>());
        for (int &num : nums)
            buckets[(num - minVal) / n].push_back(num);
        int idx = 0;
        for (auto &bucket : buckets) {
            sort(bucket.begin(), bucket.end());
            for (int &num : bucket)
                nums[idx++] = num;
        }   
    }
public:
    vector<int> sortArray(vector<int>& nums) {
        bucketSort(nums, -50000, 50000);
        return nums;
    }
};

10. 基数排序

class Solution {
private:
    void radixSort(vector<int> &nums, int minVal, int maxVal) {
        int newMaxVal = maxVal - minVal;
        int maxDigit = 0;
        while (newMaxVal) {
            maxDigit += 1;
            newMaxVal /= 10;
        }
        vector<vector<int> > buckets(10, vector<int>());
        int div = 1;
        for (int i = 0; i < maxDigit; ++i) {
            for (auto &bucket : buckets)
                bucket.clear();
            for (int &num : nums)
                buckets[(num - minVal) / div % 10].push_back(num);
            int idx = 0;
            for (auto &bucket : buckets)
                for (int &num : bucket)
                    nums[idx++] = num;
            div *= 10;
        }
    }
public:
    vector<int> sortArray(vector<int>& nums) {
        radixSort(nums, -50000, 50000);
        return nums;
    }
};
posted @   tach1koma  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
点击右上角即可分享
微信分享提示