- //冒泡 通过多次交换相邻元素将较大(或较小)的元素逐渐 "浮" 到数组的一端。该算法的时间复杂度为 O(N^2)。
- void bubbleSort(vector<int>&arr) {
- int n=arr.size();
- for(int i=0; i
-1; i++) { - for(int j=0; j
-1; j++) { - if(arr[j]>arr[j+1]) {
- swap(arr[j],arr[j+1]);
- }
- }
- }
- }
两层循环,一次次比较交换。
- //选择排序 在每次迭代中选择未排序部分的最小(或最大)元素,并将其放在已排序部分的末尾。时间复杂度为 O(N^2)。
-
- void selectionSort(std::vector<int>& arr) {
- int n = arr.size();
- for(int i=0; i
- int minIndex=i;
- for(int j=i+1; j
//找未排序部分的最小值对应的index - if(arr[j]
- minIndex=j;
- }
- }
- //找到未排序部分的最小值之后,需要放在有序部分的末尾,也就是i位置.所以交换.
- swap(arr[i],arr[minIndex]);
- }
- }
-
在未排序部分选一个最小的放到有序部分末尾。
插入排序
- //插入排序 将未排序部分的元素逐个插入到已排序部分的正确位置。时间复杂度为 O(N^2),但对于小型数据集或部分已排序的数据,插入排序具有较好的性能。
- void insertionSort(std::vector<int>& arr) {
- int n = arr.size();
- for (int i = 1; i < n; ++i) {
- int key = arr[i];
- int j = i - 1;
- while (j >= 0 && arr[j] > key) {
- arr[j + 1] = arr[j];
- --j;
- }
- arr[j+1]=key;
- }
- }
从未排序部分取一个插入到有序部分。
快速排序
- //快速排序(Quick Sort):也是采用分治策略的排序算法,通过选择一个基准值,将数据分为小于基准值和大于基准值的两部分,然后递归地对这两部分进行排序。时间复杂度为 O(NlogN),具有较好的性能。
- // 将数组以升序进行排列!
- // 分区操作函数,将数组分成两个部分并返回基准元素的最终位置
- void quickSort(vector<int> &nums, int l, int r) {
- if (l + 1 >= r) {
- return;
- }
- int first = l, last = r - 1, key = nums[first];
- while (first < last) {
- while(first < last && nums[last] > key) {
- --last;
- }//从右往左找小于基枢的值
- nums[first] = nums[last];
- //把小于基枢的值赋给左边.
- while (first < last && nums[first] < key) {
- ++first;
- }//从左往右找大于基枢的值
- nums[last] = nums[first]; //找到之后把这个大于基枢的值再赋给右边.
- }//这样循环下去,first指向的位置最终左边都是小于基枢,右边都是大于基枢. first=last把基枢位置确定下来.
- nums[first] = key;
- quickSort(nums, l, first);
- quickSort(nums, first + 1, r);
- }
分支法,先分区,找到分区的位置后,两边继续
quickSort(nums, l, first);
quickSort(nums, first + 1, r);
首先设置第一个为基枢。从右往左找比基枢小的值,然后复制到first,接着从first向右找第一个比基枢大的值,复制到fast位置,然后fast往左找小的,再给first赋值,直到first和last相等,此次,基枢位置确定,把最开始设置的基枢赋值过来。基枢位置确定之后,就有了左右分区。在左右分区继续快排。
归并排序
- //归并排序
- void merge_sort(vector<int> &nums, int l, int r, vector<int> &temp) {
- if (l + 1 >= r) {
- return;
- }
- // divide
- int m = l + (r - l) / 2;
- merge_sort(nums, l, m, temp);
-
- merge_sort(nums, m, r, temp);
- // conquer
- int p = l, q = m, i = l;
- while (p < m || q < r) {
- if (q >= r || (p < m && nums[p] <= nums[q])) {
- temp[i++] = nums[p++];
- } else {
- temp[i++] = nums[q++];
- }
- }
- for (i = l; i < r; ++i) {
- nums[i] = temp[i];
- }
- }
在合并过程中,我们使用双指针 p 和 q 分别指向左右两个子数组的起始位置,然后比较指针位置处的元素大小,将较小的元素放入临时数组 temp 中。最后,将临时数组中的元素复制回原数组。
- int main() {
- std::vector<int> numbers = {5, 2, 8, 1, 3};
-
- // std::sort(numbers.begin(), numbers.end());
- //快排 std::sort:使用快速排序(Quick Sort)实现的排序算法,平均时间复杂度为 O(NlogN)
- // std::stable_sort(numbers.begin(), numbers.end());
- //std::stable_sort:使用归并排序(Merge Sort)实现的排序算法,保持相等元素的相对顺序。时间复杂度为 O(NlogN)
- // bubbleSort(numbers);//冒泡排序的平均时间复杂度为 O(N^2)
- // selectionSort(numbers);//选择排序的时间复杂度为 O(N^2)
- // insertionSort(numbers);//插入排序的时间复杂度为 O(N^2)
- // quickSort(numbers,0,numbers.size());
- vector<int> temp(numbers.size());
- merge_sort(numbers, 0, numbers.size(), temp);
-
-
- std::cout << "Sorted numbers: ";
- for (int num : numbers) {
- std::cout << num << " ";
- }
- std::cout << std::endl;
-
- return 0;
- }
是否稳定
-
稳定的排序算法:
- 冒泡排序(Bubble Sort)
- 插入排序(Insertion Sort)
- 归并排序(Merge Sort)
- 基数排序(Radix Sort)
-
不稳定的排序算法:
- 选择排序(Selection Sort)
- 快速排序(Quick Sort)
- 堆排序(Heap Sort)
- 希尔排序(Shell Sort)
时间复杂度
- 冒泡排序、插入排序、选择排序的时间复杂度为 O(n^2)。
- 归并排序、快速排序、堆排序的平均时间复杂度为 O(n log n)。
- 基数排序的时间复杂度为 O(d * (n + k))
空间复杂度
空间复杂度是指算法在运行过程中所需要的额外的存储空间大小。以下是几种常见排序算法的空间复杂度:
-
冒泡排序(Bubble Sort):空间复杂度为 O(1),因为只需要常数级别的额外空间用于交换元素。
-
插入排序(Insertion Sort):空间复杂度为 O(1),因为只需要常数级别的额外空间用于交换元素。
-
选择排序(Selection Sort):空间复杂度为 O(1),因为只需要常数级别的额外空间用于交换元素。
-
归并排序(Merge Sort):归并排序是一种分治算法,在归并过程中需要额外的空间来存储临时数组,所以空间复杂度为 O(n)。
-
快速排序(Quick Sort):快速排序是一种原地排序算法,通常不需要额外的空间,但是如果使用递归实现,则需要系统栈来存储递归调用的上下文,因此空间复杂度在最坏情况下可能达到 O(n),平均情况下为 O(log n)。
-
堆排序(Heap Sort):堆排序是一种原地排序算法,不需要额外的空间,因此空间复杂度为 O(1)。
-
希尔排序(Shell Sort):希尔排序是一种改进的插入排序算法,空间复杂度取决于间隔序列的选择,一般为 O(1) 到 O(n)。
-
基数排序(Radix Sort):基数排序需要额外的空间来存储桶,空间复杂度取决于数据的范围和位数,一般为 O(n + k),其中 n 是数组长度,k 是数据的范围。
-
相关阅读:
计算机网络第六章——应用层(下)
thonny的汉字编码是UTF-8,如何才能转为GB2312?
从“交易核心”到“数据核心”,国产数据库要换道超车丨数据猿专访
【Javascript】数组的基本操作
【FPGA项目】沙盘演练——基础版报文收发
mysql检查表、分析表、优化表
如何入门网络安全有什么条件呢?持有NISP或CISP证书可敲门
【数据分享】厦门市共享单车数据
美格智能Cat.1蜂窝IPC解决方案 助力安防监控智慧连接
java计算机毕业设计springboot+vue超时代停车场管理平台系统(源码+系统+mysql数据库+Lw文档)
-
原文地址:https://blog.csdn.net/hyf1712011164/article/details/136731701