十大排序(代码+注释)

#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
#include <ctime>
#include <queue>
#include<stack>
using namespace std;

class Sort {
public:
    void print(vector<int>nums, string sort) {
        cout << sort << ":";
        for (int i : nums) {
            cout << i << " ";
        }
    }

    void HaoSort(vector<int>& nums, int n) {
        for (int i = 0; i < n - 1; i++) {
            for (int j = i + 1; j < n; j++) {
                if (nums[i] > nums[j]) swap(nums[i], nums[j]);
            }
        }
    }

    //冒泡排序
    void BubbleSort(vector<int>& nums, int n) {
        for (int i = 0; i < n; i++) {
            int exchange = 0;
            for (int j = 1; j < n - i; j++) {
                if (nums[j] < nums[j - 1]) {
                    swap(nums[j - 1], nums[j]);
                    exchange = 1;
                }
            }
            if (exchange == 0) break;//说明已经有序 此时最好情况下为O(N)
        }
    }

    //直接选择排序(优化排序,一次找两个数)
    //O(N*N)
    void SelectSort(vector<int>& nums, int n) {
        int begin = 0;
        int end = n - 1;
        while (begin < end) {
            int mini = begin;//当前最小数的下标
            int maxi = begin;//当前最大数的下标
            for (int i = begin; i <= end; i++) {
                if (nums[i] < nums[mini]) mini = i;
                if (nums[i] > nums[maxi]) maxi = i;
            }
            swap(nums[mini], nums[begin++]);
            if (maxi == begin) maxi = mini;//如果begin跟maxi重叠 需要修正maxi
            swap(nums[maxi], nums[end--]);
        }

    }

    //插入排序
    //O(n^2)
    void InsertSort(vector<int>& nums, int n) {
        for (int i = 1; i < n; i++) {
            int end = i;
            while (end) {
                if (nums[end - 1] > nums[end]) {//后移 并且end前移
                    swap(nums[end - 1], nums[end]);
                    end--;
                }
                else{
                    break;
                }
            }
        }

    }

    //希尔排序
    //改进的插入排序算法
    //分组排序 预排序
    //时间复杂度:O(N*logN)
    //平均时间复杂度:O(log1.3N)
    void ShellSort(vector<int>& nums, int n) {
        int gap = n;
        while (gap > 1) {
            gap = gap / 3 + 1;//调整希尔变量 O(log3N)
            //当gap很大时,下面预排序时间复杂度O(N)
            //当gap很小时,这时已经接近有序 预排序时间复杂度O(N)
            for (int i = gap; i < n; i++) {
                int end = i;
                while (end>=gap) {
                    if (nums[end-gap] > nums[end]) {//后移 并且end前移
                        swap(nums[end], nums[end-gap]);
                        end-=gap;
                    }
                    else {
                        break;
                    }
                }
            }
        }

    }

    //堆排序
    //O(n*logn)
    //堆的两个特性
    //结构性:用数组表示的完全二叉树
    //有序性:任一节点的关键字是其子树所有节点的最大值(或最小值)
    //“最大堆”,也称为“大顶堆”:最大值 所有parent大于等于child
    //“最小堆”,也称为“小顶堆”:最小值 所有parent小于等于child
    void AdjustDown(vector<int>& nums, int n, int root) {
        int parent = root;
        int child = parent * 2 + 1;//默认为左孩子
        while (child < n) {
            //1.选出左右孩子中大的一个
            if (child + 1 < n && nums[child + 1] > nums[child]) {
                child++;
            }
            if (nums[child] > nums[parent]) {
                swap(nums[child], nums[parent]);
                parent = child;
                child = parent * 2 + 1;
            }
            else {
                break;
            }
        }
    }

    void HeapSort(vector<int>& nums, int n) {
        //建堆
        for (int i = (n - 1 - 1) / 2; i >= 0; i--) {
            AdjustDown(nums, n, i);
        }
        int end = n - 1;
        while (end) {
            swap(nums[0], nums[end]);
            AdjustDown(nums, end--, 0);
        }

    }

    //基数排序
    //O(n*k)
    void RadixSort(vector<int>& nums, int n) {
        //定义临时二维数组表示十个堆
        vector<vector<int>> temp(10, vector<int>(n));
        //定义一个一维数组 记录在temp中相应的数组中存放数字的数量
        vector<int> counts(10);
        //找到数组中最大数
        int max = *max_element(nums.begin(), nums.end());
        //计算最大数字是几位数 获得轮回次数
        int maxLength = (to_string)(max).size();
        for (int i = 0, k = 1; i < maxLength; i++, k *= 10) {
            //把每一个数字分别计算余数(个位十位百位.....)
            for (int j = 0; j < n; j++) {
                //计算余数(个位十位百位.....) num = 0~9
                int num = nums[j] / k % 10;
                temp[num][counts[num]] = nums[j];
                //记录数量
                counts[num]++;
            }
            //记录取元素需要放的位置
            int index = 0;
            //把数字取出来
            for (int j = 0; j < 10; j++) {
                //循环取出元素
                for (int w = 0; w < counts[j]; w++) {
                    nums[index++] = temp[j][w];
                }
                counts[j] = 0;

            }
        }
    }

    //计数排序:适用范围具有局限性
    //非比较排序
    //适用于范围集中的整数集合
    //时间复杂度:O(n+range)
    //空间复杂度:O(range)
    void CountSort(vector<int>&nums,int n) {
        int max = *max_element(nums.begin(), nums.end());
        int min = *min_element(nums.begin(), nums.end());
        int range = max - min+1;
        vector<int> count(range,0);
        for (int i = 0; i < n; i++) {
            count[nums[i] - min]++;
        }
        int index = 0;
        for (int i = 0; i < range; i++) {
            while (count[i]--) {
                nums[index++] = i + min;
            }
        }
    }

    //三数取中
    int GetMidIndex(vector<int> &nums, int left, int right) {
        int mid = (left + right) >> 1;
        if (nums[left] > nums[mid]) swap(nums[left], nums[mid]);
        if (nums[right] < nums[mid]) swap(nums[right], nums[mid]);
        return mid;
    }

    //快速排序
    //O(N*logN)
    //挖坑法
    //左右指针
    int PartSort1(vector<int>&nums,int left,int right) {
        int begin = left, end = right;
        int pivot = GetMidIndex(nums, left, right);//坑位
        int key = nums[pivot];//关键值
        //单趟排序O(N)
        while (begin < end) {
            //右边找小
            while (begin < end && nums[end] >= key) end--;
            nums[pivot] = nums[end];//填坑位
            pivot = end;//挖坑位

            //左边找大
            while (begin < end && nums[begin] <= key) begin++;
            nums[pivot] = nums[begin];
            pivot = begin;
        }
        nums[begin] = key;
        return begin;
    }

    //左右指针
    int PartSort2(vector<int>& nums, int left, int right) {
        int begin = left, end = right;
        int index = GetMidIndex(nums, left, right);//坑位
        swap(nums[left], nums[index]);
        int key = nums[left];//关键值
        //单趟排序
        while (begin < end) {
            while (begin < end && nums[end] >= key) {
                end--;
            }
            while (begin < end&&nums[begin] <= key) {
                begin++;
            }

            swap(nums[begin], nums[end]);
        }
        swap(nums[begin], nums[left]);
        return begin;
    }

    int PartSort3(vector<int>& nums, int left, int right) {
        int index = GetMidIndex(nums, left, right);
        swap(nums[index], nums[left]);
        int pivot = nums[left];
        int prev = left;
        int cur = left+1;
        while (cur <= right) {
            if (nums[cur] <pivot) {
                ++prev;
                swap(nums[prev], nums[cur]);
            }
            ++cur;
        }
        swap(nums[prev], nums[left]);
        return prev;
    }

    //时间复杂度:O(N*logN)
    void QuickSort(vector<int>& nums, int left, int right) {
        if (right <= left) return;
        int pivot = PartSort3(nums, left, right);

        //分治递归
        //[left,right]
        //[left,pivot-1] pivot [pivot+1,right]
        QuickSort(nums,pivot+1, right);//右边
        QuickSort(nums,left, pivot-1);//左边XXX

        //if (pivot - 1 - left > 10) {
        //	QuickSort(nums, pivot + 1, right);
        //}
        //else{
        //	sort(nums.begin() + left, nums.begin() + pivot);
        //}
        //if (right - (pivot + 1) > 10) {
        //	QuickSort(nums, left, pivot - 1);
        //}
        //else {
        //	sort(nums.begin() + pivot + 1, nums.begin() + right);
        //}
    }

    //非递归qsort
    void QuickSortNond(vector<int>& nums,int n){
        stack<int> s;
        s.push(n - 1);
        s.push(0);
        while (s.size()) {
            int left = s.top();
            s.pop();
            int right = s.top();
            s.pop();
            int keyi = PartSort2(nums, left, right);
            if (left < keyi) {
                s.push(keyi);
                s.push(left);
            }
            if (right > keyi + 1) {
                s.push(right);
                s.push(keyi+1);
            }
        }

    }

    //归并排序
    //O(N*logN)
    void MergeSort(vector<int>& nums,int left,int right) {
        if (left >= right) return;
        int mid = (right + left) >> 1;
        //递归拆分
        //[left,mid] [mid+1,right]
        MergeSort(nums, left, mid);//左半部分
        MergeSort(nums, mid+1, right);//右半部分

        //合并
        //队列顺序存储元素
        queue<int> q;
        //左部分
        int begin1 = left, end1 = mid;
        //右部分
        int begin2 = mid + 1, end2 = right;
        //左右部分对比 元素顺序入队列
        while (begin1 <= end1 && begin2 <= end2) {
            if (nums[begin1] < nums[begin2]){
                q.push(nums[begin1++]);
            }
            else {
                q.push(nums[begin2++]);
            }
        }
        //剩余元素入队列
        while (begin1 <= end1) {
            q.push(nums[begin1++]);
        }
        while (begin2 <= end2) {
            q.push(nums[begin2++]);
        }
        //copy回去
        int index = left;
        while (q.size()) {
            nums[index++] = q.front();
            q.pop();
        }

    }

    //非递归
    void MergeSortNond(vector<int>& nums, int n) {
        int gap = 1;//每组数据个数
        //队列顺序存储元素
        queue<int> q;
        while (gap < n) {
            for (int i = 0; i < n; i += 2 * gap) {
                int begin1 = i, end1 = i + gap-1;
                int begin2 = i + gap, end2 = i + 2 * gap - 1;

                //归并过程中右区间不存在
                //此时直接结束循环
                if (begin2 >= n) break;
                //归并过程中右区间存在一部分
                if (end2 >= n) end2 = n - 1;

                //左右部分对比 元素顺序入队列
                while (begin1 <= end1 && begin2 <= end2) {
                    if (nums[begin1] < nums[begin2]) {
                        q.push(nums[begin1++]);
                    }
                    else {
                        q.push(nums[begin2++]);
                    }
                }
                //剩余元素入队列
                while (begin1 <= end1) {
                    q.push(nums[begin1++]);
                }
                while (begin2 <= end2) {
                    q.push(nums[begin2++]);
                }
            }
            //每一轮copy回去
            int index = 0;
            while (q.size()) {
                nums[index++] = q.front();
                q.pop();
            }
            gap *= 2;//合并
        }
    }

    //排序的性能对比
    void TestOP() {
        srand(time(0));
        const int N = 100000;
        vector<int> nums1(N);
        vector<int> nums2(N);
        vector<int> nums3(N);
        vector<int> nums4(N);
        vector<int> nums5(N);
        vector<int> nums6(N);
        vector<int> nums7(N);
        vector<int> nums8(N);
        vector<int> nums9(N);

        for (int i = 0; i < N; i++) {
            nums1[i] = rand();
            nums2[i] = nums1[i];
            nums3[i] = nums1[i];
            nums4[i] = nums1[i];
            nums5[i] = nums1[i];
            nums6[i] = nums1[i];
            nums7[i] = nums1[i];
            nums8[i] = nums1[i];
            nums9[i] = nums1[i];
        }

        int begin = clock();
        SelectSort(nums1, N);
        int end = clock();
        cout << "SelectSort:" << end - begin << endl;

        begin = clock();
        BubbleSort(nums8, N);
        end = clock();
        cout << "BubbleSort:" << end - begin << endl;

        begin = clock();
        InsertSort(nums2, N);
        end = clock();
        cout << "InsertSort:" << end - begin <<endl;

        begin = clock();
        ShellSort(nums3, N);
        end = clock();
        cout << "ShellSort:" << end - begin << endl;

        begin = clock();
        HeapSort(nums4, N);
        end = clock();
        cout << "HeapSort:" << end - begin << endl;

        begin = clock();
        RadixSort(nums5, N);
        end = clock();
        cout << "RadixSort:" << end - begin<<endl;

        begin = clock();
        QuickSort(nums6,0, N-1);
        end = clock();
        cout << "QuickSort:" << end - begin << endl;

        begin = clock();
        MergeSort(nums7, 0, N - 1);
        end = clock();
        cout << "MergeSort:" << end - begin << endl;

        begin = clock();
        CountSort(nums8,N);
        end = clock();
        cout << "CountSort:" << end - begin << endl;
    }

};


int main() {
    Sort sort;
    vector<int> nums = { 6,5,2,7,8,3,1,9,4,0};
    int n = nums.size();
    //sort.InsertSort(nums,n);
    //sort.print(nums,"InsertSort");

    //sort.HeapSort(nums,n);
    //sort.RadixSort(nums, n);
    //sort.SelectSort(nums, n);

    //sort.ShellSort(nums, n);
    //sort.print(nums, "ShellSort:");


    //sort.HaoSort(nums, n);
    //sort.print(nums, "Haosort:");

    //sort.BubbleSort(nums, n);
    //sort.print(nums, "BubbleSort:");

    //sort.QuickSort(nums, 0,n-1);
    //sort.print(nums, "QuickSort:");

    //sort.MergeSort(nums,0,n-1);
    //sort.print(nums, "MergeSort:");

    //sort.QuickSortNond(nums,n);
    //sort.print(nums, "QuickSortNond:");

    //sort.MergeSortNond(nums,n);
    //sort.print(nums, "MergeSortNond:");

    //sort.CountSort(nums,n);
    //sort.print(nums, "CountSort:");

    sort.TestOP();

    return 0;
}

十万数据排序时间对比:

SelectSort:19565
BubbleSort:55163
InsertSort:29196
ShellSort:40
HeapSort:35
RadixSort:13
QuickSort:19
MergeSort:109
CountSort:3

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值