十大排序算法C++实现

十大排序算法C++实现

本章对十大排序算法进行C++代码实现,可以前往力扣进行验证,其中冒泡,选择,插入,快排会超时。
Leetcode912数组排序
排序稳定性指的是:所有相等的数经过某种排序后,仍能保持排序前的相对次序,这种排序方法是稳定的。

例如:arr = [5 8 5 2 9]使用选择排序是不稳定的,因为前面的5跑到后面去了

贴两张图归类一下
请添加图片描述
请添加图片描述

冒泡法

vector<int> sortArray(vector<int>& nums) {//冒泡法
        for(int i=0;i<nums.size()-1;i++){
            for(int j=0;j<nums.size()-i-1;j++){
                if(nums[j]>nums[j+1]){
                    int temp=nums[j];
                    nums[j]=nums[j+1];
                    nums[j+1]=temp;
                }
            }
        }
        return nums;
}

冒泡法优化

vector<int> sortArray(vector<int>& nums) {//冒泡法优化
    int n = nums.size();
    bool swapped; // 标志位,用于检测是否发生了交换

    for (int i = 0; i < n - 1; i++) {
        swapped = false; // 初始化标志位为假
        for (int j = 0; j < n - i - 1; j++) {
            if (nums[j] > nums[j + 1]) {
                swap(nums[j], nums[j + 1]); // 交换元素位置
                swapped = true; // 设置标志位为真
            }
        }        // 如果在一轮遍历中没有发生交换,说明数组已经有序,提前退出
        if (!swapped) {
            break;
        }
    }
    return nums;
}

快速排序

取第一个数为基准值,小的放左边,大的放右边,重复直到i==j,再继续选取基准值

vector<int> sortArray(vector<int>& nums) {//快速排序
        Quick(nums,0,nums.size()-1);
        return nums;
    }
    void Quick(vector<int>& nums,int start,int end){
        if(start>=end)return;
        int i=start;
        int j=end;
        int baseval=nums[start];
        while(i<j){
            while(i<j&&nums[j]>=baseval){// 从右向左找比基准数小的数
                j--;
            }
            if(i<j){
                nums[i]=nums[j];
                i++;
            }
            while(i<j&&nums[i]<=baseval){// 从左向右找比基准数大的数
                i++;
            }
            if(i<j){
                nums[j]=nums[i];
                j--;
            }
        }
        nums[i]=baseval;//i和j相等,可以分区间了
        Quick(nums,start,i-1);
        Quick(nums,i+1,end);
}

快排优化 随机选择基准值、插入排序优化、三数取中法

vector<int> sortArray(vector<int>& nums) {
    Quick(nums, 0, nums.size() - 1);
    return nums;
}

void Quick(vector<int>& nums, int start, int end) {
    if (start >= end) return;
    if (end - start + 1 <= 10) { // 切换到插入排序
        InsertionSort(nums, start, end);
        return;
    }
    
    // 随机选择基准值
    int pivotIdx = start + rand() % (end - start + 1);
		// 选完交换一下
    swap(nums[start], nums[pivotIdx]);
    
    int i = start;
    int j = end;
    int baseval = nums[start];
    
    while (i < j) {
        while (i < j && nums[j] >= baseval) j--;
        while (i < j && nums[i] <= baseval) i++;
        if (i < j) swap(nums[i], nums[j]);
    }
    
    nums[start] = nums[i];
    nums[i] = baseval;
    
    Quick(nums, start, i - 1);
    Quick(nums, i + 1, end);
}

void InsertionSort(vector<int>& nums, int start, int end) {
    for (int i = start + 1; i <= end; i++) {
        int key = nums[i];
        int j = i - 1;
        while (j >= start && nums[j] > key) {
            nums[j + 1] = nums[j];
            j--;
        }
        nums[j + 1] = key;
    }
}

插入排序

对近有序的序列更高效,时间复杂度更接近O(n)

```cpp
vector<int> sortArray(vector<int>& nums) {**//插入排序,对近有序的序列更高效,时间复杂度更接近O(n)**
        for(int i=1;i<nums.size();i++){
            int j=i-1;
            int key=nums[i];
            while(j>=0&&nums[j]>key){
                nums[j+1]=nums[j];
                j--;
            }
            nums[j+1]=key;
        }
        return nums;
    }

希尔排序

对数组执行多次间隔的插入排序,也叫最小增量排序,通常除以2,间隔排序,最后来一次总插入排序

vector<int> sortArray(vector<int>& nums) {//希尔排序
        int len=nums.size();
        int increasement = len;
        int i, j, k;
        while (increasement > 1) {
            // 确定分组的增量
            increasement = increasement / 2 ;//增量为2
            for (i = 0; i < increasement; i++) {
                for (j = i + increasement; j < len; j += increasement) {
                    if (nums[j] < nums[j - increasement]) {
                        int temp = nums[j];
                        for (k = j - increasement; k >= 0 && temp < nums[k]; k -=increasement) {
                            nums[k + increasement] = nums[k];
                        }
                        nums[k + increasement] = temp;
                    }
                }
            }
        }
        return nums;
}

希尔排序经典写法

vector<int> sortArray(vector<int>& nums) {//希尔排序,更经典的写法
    int n = nums.size();
    for (int gap = n / 2; gap > 0; gap /= 2) {
        for (int i = gap; i < n; i++) {
            int temp = nums[i];
            int j = i;
            while (j - gap >= 0 && nums[j - gap] > temp) {
                nums[j] = nums[j - gap];
                j -= gap;
            }
            nums[j] = temp;
        }
    }
    return nums;
}

选择排序

vector<int> sortArray(vector<int>& nums) {//选择排序
        for(int i=0;i<nums.size();i++){
            int min=i;
            for(int j=i+1;j<nums.size();j++){
                if(nums[min]>nums[j]){
                    min=j;
                }
            }
						if(i!=min){
								swap(nums[min],nums[i]);//优化,当min和i不相等才交换,影响不大
						}
            
        }
        return nums;
}

归并排序(分治法)

有序数组A+有序数组——>有序数组A+B,将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。代价是需要额外的内存空间。

vector<int> sortArray(vector<int>& nums) {//归并排序
        mergeSort(nums,0,nums.size()-1);
        return nums;
    }
    void mergeSort(std::vector<int>& nums, int left, int right) {
        if (left < right) {//只有一个数字的时候不再分割子序列
            int mid = left + (right - left) / 2;
            mergeSort(nums, left, mid);
            mergeSort(nums, mid + 1, right);
            merge(nums, left, mid, right);
        }
    }
    void merge(std::vector<int>& nums, int left, int mid, int right) {
        int n1 = mid - left + 1;
        int n2 = right - mid;
        std::vector<int> leftArr(n1);
        std::vector<int> rightArr(n2);
        for (int i = 0; i < n1; i++) {
            leftArr[i] = nums[left + i];
        }
        for (int i = 0; i < n2; i++) {
            rightArr[i] = nums[mid + 1 + i];
        }
        int i = 0, j = 0, k = left;
        while (i < n1 && j < n2) {
            if (leftArr[i] <= rightArr[j]) {
                nums[k] = leftArr[i];
                i++;
            } else {
                nums[k] = rightArr[j];
                j++;
            }
            k++;
        }
        while (i < n1) {
            nums[k] = leftArr[i];
            i++;
            k++;
        }
        while (j < n2) {
            nums[k] = rightArr[j];
            j++;
            k++;
        }
}

计数排序

元素值即下标

vector<int> sortArray(std::vector<int>& nums) {//计数排序
    if (nums.empty()) {
        return nums;
    }
    // 找到数组中的最大值和最小值
    int max_num = *std::max_element(nums.begin(), nums.end());
    int min_num = *std::min_element(nums.begin(), nums.end());
    // 计算计数数组的大小
    int range = max_num - min_num + 1;
    // 创建计数数组并初始化为0
    vector<int> count(range, 0);
    // 统计每个元素的出现次数
    for (int num : nums) {
        count[num - min_num]++;
    }
    // 根据计数数组重新构建排序后的数组
    int index=0;
    for(int i=0;i<range;i++){
        while(count[i]>0){
            nums[index]=i + min_num;
            index++;
            count[i]--; 
        }
    }    
    return nums;
}

桶排序

数组分配到若干桶,各自排序后返回

vector<int> sortArray(vector<int>& nums) {//桶排序
    if (nums.empty()) {
        return nums;
    }
    // 找到数组中的最大值和最小值
    int max_num = *std::max_element(nums.begin(), nums.end());
    int min_num = *std::min_element(nums.begin(), nums.end());
    // 计算计数数组的大小
// 计算桶的数量,每个桶的范围是 (max_num - min_num + 1) / nums.size(),加 1 是为了包括最大值
    int bucket_count = (max_num - min_num + 1) / nums.size() + 1;
    // 创建桶并初始化为空
    vector<vector<int>> buckets(bucket_count);
    // 将元素分配到对应的桶中
    for (int num : nums) {
        int bucket_index = (num - min_num) / nums.size();
        buckets[bucket_index].push_back(num);
    }
    // 对每个桶中的元素进行排序(可以使用其他排序算法,如插入排序)
    for (vector<int>& bucket : buckets) {
        sort(bucket.begin(), bucket.end());
    }
    // 合并各个桶的排序结果
    nums.clear();
    for (const vector<int>& bucket : buckets) {
        nums.insert(nums.end(), bucket.begin(), bucket.end());
    }
    return nums;
}

基数排序

数字逐位比较。个位数排序,十位数排序,百位数排序。。。以此类推

vector<int> sortArray(vector<int>& nums) {//基数排序
        int n = nums.size();
        vector<int> arr(n);
        //获取数组中最小值
        int min = nums[0];
        for (int i = 0; i < n; i++) {
            min = std::min(min, nums[i]);
        }
        //把负数转为正数
        for (int i = 0; i < n; i++) {
            nums[i] -= min;
        }
        //基数排序
        radixSort(nums);
        //还原
        for (int i = 0; i < n; i++) {
            nums[i] += min;
        }
        return nums;
    }
    void radixSort(vector<int>& arr) {
        int max = getMax(arr);
        // 对每个位进行计数排序,位数从个位开始,直到最高位
        for (int exp = 1; max / exp > 0; exp *= 10) {
            countingSort(arr, exp);
        }
    }
    int getMax(vector<int>& arr) {
        int max = arr[0];
        for (int i = 1; i < arr.size(); i++) {
                max = std::max(arr[i],max);
        }
        return max;
    }
    void countingSort(vector<int>& arr, int exp) {
        int n = arr.size();
        vector<int> output(n); // 存储排序结果的临时数组
        vector<int> count(10, 0); // 计数数组,用于统计每个位置上的数字的出现次数

        // 统计每个位置上数字的出现次数
        for (int i = 0; i < n; i++) {
            int digit = (arr[i] / exp) % 10;
            count[digit]++;
        }
        // 将计数数组中的值累加,确定每个数字在输出数组中的位置
        for (int i = 1; i < 10; i++) {
            count[i] += count[i - 1];
        }
        // 根据计数数组将数字放入输出数组中,从后往前才能达到基数排序的效果
        for (int i = n - 1; i >= 0; i--) {
            int digit = (arr[i] / exp) % 10;
            count[digit]--;
            output[count[digit]] = arr[i];
        }
        // 将输出数组拷贝回原数组
        arr = output;
}

小知识:sort函数是C++标准库提供的用于对容器中的元素进行排序的函数。底层原理通常使用一种高效的排序算法,通常是快速排序(Quicksort)或归并排序(Mergesort),取决于具体的实现和输入数据的大小。C++标准库的具体实现可能因不同的编译器和标准库版本而异。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值