本文介绍: 详细介绍了桶排序,冒泡排序以及快速排序,std::sort


前言

今天学习了一些简单的排序算法,其实在我们平时解决问题中经常用到,今天正好一起看了看,记录一下。如果对你也有帮助,我很开心~


一、桶排序(Bucket Sort)

桶排序是一种排序算法,它将数组划分为一些有序的桶,然后每个桶再分别排序。最后,将所有的桶合并起来,得到一个有序的数组。桶排序的核心思想是将数据分散到不同的桶中,每个桶内部进行排序,最后将所有桶的数据合并

思路:

  1. 确定桶的数量,并创建这些桶
  2. 遍历原始数组,将每个元素放入相应的桶中
  3. 对每个桶内部进行排序。可以使用其他排序算法,或者递归地使用桶排序
  4. 将所有桶的元素按顺序合并成最终的有序数组

适用于数据分布比较均匀的情况,因为如果每个桶的大小相对一致,就减少了在桶内进行排序的工作量,时间复杂度桶的数量每个桶内采用的内部排序算法相关

小唐有话说:我感觉桶排序也是拿空间换时间的感觉,和哈希表有点像有没有!!!但是他们的主要的区别在于桶排序是一种排序算法,重于对元素的排序,而哈希表是一种数据结构,用于快速查找和插入

// 桶排序函数
void bucketSort(vector<float>& arr) {
    // 找到最大值和最小值
    //*max_element,*min_element是 C++ 标准库 <algorithm> 头文件中的函数,分别用于找到范围内的最大值和最小值。
    float max_val = *max_element(arr.begin(), arr.end());
    float min_val = *min_element(arr.begin(), arr.end());
    int bucket_count = 10; // 这里假设使用 10 个桶
    vector<vector<float>> buckets(bucket_count);// 创建桶
    // 将元素放入桶中
    for (float num : arr) {//是 C++11 引入的一种基于范围的 for 循环语法,也称为范围-based for循环
        //表示遍历浮点数数组 arr 中的每个元素,并将每个元素赋值给变量 num,然后执行循环体内的操作。
        int index = int(bucket_count * (num - min_val) / (max_val - min_val));
        buckets[index].push_back(num);
    }
    // 对每个桶内部进行排序,这里使用标准库的排序函数
    for (auto& bucket : buckets) {
        sort(bucket.begin(), bucket.end());
    }
    // 将所有桶的元素合并
    arr.clear();
    for (const auto& bucket : buckets) {
        arr.insert(arr.end(), bucket.begin(), bucket.end());
    }
}

对于此处的例子,时间复杂度: O(n + 10 * log(10)),其中10是是因为分了10个桶,分桶的过程时间复杂度是 O(n),std::sort是一种改进的快速排序算法,它的平均时间复杂度是O(n log n)

二、冒泡排序(Bubble Sort)

冒泡排序是一种简单的排序算法,其基本思想是通过不断地交换相邻元素,将较大的元素逐渐移到右侧(或较小的元素逐渐移到左侧),从而达到排序的目的
小唐有话说:不知道大家有没有印象!反正小唐印象超级无敌深刻,大一学C语音的时候就对它印象深刻,到现在仍然记忆尤新,当初看了好多好多遍才弄懂的算法,现在看简直简单的不能再简单,这就是轻舟已过万重山叭!

思路:

  1. 从第一个元素开始,依次比较相邻的两个元素
  2. 如果发现顺序不对(即当前元素大于下一个元素),则交换这两个元素的位置
  3. 继续进行相邻元素的比较和交换,直到整个序列变得有序
  4. 重复上述步骤,每次都会确定一个最大(或最小)元素的位置,直到整个序列有序为止

冒泡排序的时间复杂度为 O(n^2),因为时间复杂度较高,在实际应用中较少使用,特别是对于大规模数据集。

// 冒泡排序函数
void bubbleSort(vector<int>& arr) {
    int n = arr.size();

    for (int i = 0; i < n - 1; ++i) {
        for (int j = 0; j < n - i - 1; ++j) { //这里注意,内层循环只用到n-i-1,因为后面的已经排过啦
            // 如果当前元素大于下一个元素,则交换它们
            if (arr[j] > arr[j + 1]) {
                swap(arr[j], arr[j + 1]);
            }
        }
    }
}

二、快速排序(Quick Sort)

快速排序是一种高效的排序算法,属于比较排序的一类。它基于分治法的思想,通过选择一个基准元素,将数组分成两个子数组,使得左边的元素都小于基准元素右边的元素都大于基准元素,然后对这两个子数组分别递归地应用相同的排序算法。

思路:

  1. 选择一个基准元素(通常是数组中间的元素)
  2. 将数组分成两个子数组,左边的元素小于等于基准元素,右边的元素大于等于基准元素
  3. 对左右子数组分别递归地应用快速排序
  4. 合并排序好的左右子数组
// 快速排序函数
void quickSort(vector<int>& arr, int low, int high) {
    if (low < high) {

        int pivot = arr[high];// 选择最右边的元素作为基准元素
        int i = low - 1;
        cout << i << endl;

        // 将小于等于基准元素的元素移动到左边
        for (int j = low; j < high; ++j) {
            if (arr[j] <= pivot) {
                ++i;
                swap(arr[i], arr[j]);
            }
        }

        // 将基准元素移动到正确的位置
        swap(arr[i + 1], arr[high]);
        int pivotIndex = i + 1;

        // 递归排序左右子数组
        quickSort(arr, low, pivotIndex - 1);
        quickSort(arr, pivotIndex + 1, high);
    }
}

快速排序的平均时间复杂度为O(n log n)最差时间复杂度是 O(n^2),发生在数组已经有序或近乎有序的情况下。

写了快速排序的话就顺便在这最后介绍一下std::sort
std::sort 是 C++ 标准库提供的排序函数,其实现通常基于一种改进的快速排序算法(introsort)
相同点:
1.平均时间复杂度都为 O(n log n)
2.两者都基于分治法的思想,通过递归地划分数组并排序子数组来完成排序。
不同点:
1.std::sort 的具体实现可能会结合多种排序算法,而不仅仅是快速排序。标准库通常会选择在给定情况下最适合的排序算法,这可能包括快速排序、堆排序、插入排序等。
2.std::sort 通常是稳定排序的,即相等元素的相对顺序在排序后保持不变。而经典的快速排序算法是不稳定的,尽管可以通过一些改进策略使其成为稳定排序。
3.适应性: std::sort 可能会根据输入数据的性质在不同情况下选择不同的排序算法,以提高性能。这种自适应性是标准库排序函数的一个特点。
小唐有话说:总得来说官方给的就是比我们自己写的厉害👍!没要求自己写,咱们平时就还是用官方的叭!当然原理还是得掌握的!


总结

以上就是今天总结的内容,一些简单的排序算法,主要具体的还是根据题目随机应变,后续也会继续记录学习的一些算法呀,唐怡佳继续加油!

原文地址:https://blog.csdn.net/TYJhhxx/article/details/135509182

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_54522.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注