博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
排序-冒泡、选择、插入、快速、归并
阅读量:2398 次
发布时间:2019-05-10

本文共 4696 字,大约阅读时间需要 15 分钟。

排序算法是一种很重要的算法,虽然c++ stl中有sort函数,但是还是要了解其中常用的几种排序算法,至于std::sort源码实现使用的排序算法是混合式排序,详见std::sort源码剖析

std::sort只支持vector,array等迭代器支持随机存取的容器,因为内部是快排和堆排
std::list这种不支持随机存取,内部有单独的sort函数,实现是迭代版归并排序

有些排序算法时间复杂度都是受限原数据的排序情况的,比如最坏的情况原数组完全逆序,快速排序时间复杂度是O(n^2),但是最好的情况原数组已排序,快速排序时间复杂度是O(nlogn)

堆排序最好和最坏都是O(nlogn),但是大多数情况快排要优于堆排()

关于排序的稳定性

在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的

在这里插入图片描述

代码如下:

class Solution {public:    //冒泡排序:每次两两比较直到将最大数排到末尾,之后边界减1,继续上面操作    void bubble_sort(vector
& arr) { for (int i = 0; i < arr.size(); i++) { for (int j = 1; j < arr.size() - i; j++) { if (arr[j - 1] > arr[j]) { int tmp = arr[j - 1]; arr[j - 1] = arr[j]; arr[j] = tmp; } } } } //插入排序:先排序前面的部分,再在已排序序列中从后向前扫描,找到相应位置并插入,为什么已排序序列是从后向前扫描,因为插入后后面元素位置要往后移,从后往前扫描正好可以顺势移动 void insert_sort(vector
& arr) { for (int i = 1; i < arr.size(); i++) { int cur = arr[i]; int pre = i - 1; while (pre >= 0 && cur < arr[pre]) { arr[pre+1] = arr[pre]; pre--; } arr[pre+1] = cur; } } //选择排序: 每次记录最小值的位置和"首元素"比较大小,"首元素"递增 void select_sort(vector
& arr) { for (int i = 0; i < arr.size(); i++) { int min_index = i; for (int j = i + 1; j < arr.size(); j++) { if (arr[j] < arr[min_index]) { min_index = j; } } std::swap(arr[i], arr[min_index]); } } //快速排序(参考https://cloud.tencent.com/developer/article/1425422) int partition(std::vector
&sort_vec, int start, int end) { int pos = start + 1; // partiton最重要的就是这个参考位,为了防止移动比基准值小值需要将后续元素都往后移一位复杂度太高,这里使用一个参考位交换比基准值小的数 for (int i = start + 1; i < end; i++) { if (sort_vec[i] < sort_vec[start]) { std::swap(sort_vec[i], sort_vec[pos]); // 如果之后元素有比基准小的,先与sort_vec[pos]交换 pos++; // 基准元素sort_vec[start]先不动,pos值加一,后续再有比sort_vec[start]小的与sort_vec[pos]交换,直至退出循环 } } std::swap(sort_vec[start], sort_vec[pos - 1]); // 最后sort_vec[pos - 1]左边的(包括自己)除了sort_vec[start]都比sort_vec[start]小,右边都比sort_vec[start]大,于是交换sort_vec[start]和sort_vec[pos - 1] return pos - 1; } void quicksort(std::vector
&sort_vec, int start, int end) { if (start >= end) return; // 不断二分直至start大于end int pos = partition(sort_vec, start, end); // 调用partition函数将元素比基准值小的划到基准值左边,比基准值大的划到基准值右边 quicksort(sort_vec, start, pos - 1); // 递归左边 quicksort(sort_vec, pos + 1, end); // 递归右边 } // 归并排序, 分治思想,不断二分到只剩一个元素,然后两边已排序数组再不断比较合成一个新的排序数组,如此重复,归并排序虽然最坏时间复杂度也是nlogn,但是递归过程中有大量的临时对象复制,实际没快速排序快 std::vector
merge(std::vector
left, std::vector
right) { std::vector
tmp; int l = 0, r = 0; while (l < left.size() && r < right.size()) { if (left[l] <= right[r]) { tmp.push_back(left[l++]); } else { tmp.push_back(right[r++]); } } if (r == right.size()) { tmp.insert(tmp.end(), left.begin() + l, left.end()); } else if (l == left.size()) { tmp.insert(tmp.end(), right.begin() + r, right.end()); return tmp; } std::vector
merge_sort(std::vector
&sort_vec) { if (sort_vec.size() < 2) return sort_vec; int mid = sort_vec.size() / 2; std::vector
left(sort_vec.begin(), sort_vec.begin() + mid); std::vector
right(sort_vec.begin() + mid, sort_vec.end()); return merge(merge_sort(left), merge_sort(right)); } // 归并排序2,上一个临时对象太多,可优化一下 void merge(std::vector
&sort_vec, int left_s, int left_e, int right_s, int right_e) { int l = left_s, r = right_s; std::vector
tmp; // 这里需要一个临时数组保存这次排序好的部分元素 while (l <= left_e && r <= right_e) { if (sort_vec[l] <= sort_vec[r]) { tmp.push_back(sort_vec[l++]); } else { tmp.push_back(sort_vec[r++]); } } while (l <= left_e) tmp.push_back(sort_vec[l++]); while (r < right_e) tmp.push_back(sort_vec[r++]); // 排序好后再把数据复制会原数组 for (int i = 0; i < tmp.size(); i++) { sort_vec[left_s + i] = tmp[i]; } return; } void merge_sort(std::vector
&sort_vec, int start, int end) { if (start >= end) return; int mid = (start + end) / 2; merge_sort(sort_vec, start, mid); // 归并排序左半部分 merge_sort(sort_vec, mid + 1, end); // 归并排序右半部分 merge(sort_vec, start, mid, mid + 1, end); // 合并 }};

转载地址:http://rhdob.baihongyu.com/

你可能感兴趣的文章
[转载]窃以为软件的最大追求是在合适的地方做正确的事
查看>>
[转载] 在WEB程序中如何画图并显示
查看>>
[转载]如何动态调用DLL中类的方法以及属性
查看>>
[转载]使用 XMLBeans 在 Apache Geronimo 中部署 SOA 应用程序
查看>>
[转载]IBM WebSphere 开发者技术期刊: 使用 Rational Application Developer 中用于开发 WebSphere 软件的新 EJB 可视化编辑器...
查看>>
[转载]彻底转变流,第 2 部分:优化 Java 内部 I/O
查看>>
[转载]SWT 和 JFace, 第 2 部分: 简介
查看>>
[转载]ZX手机平台的几个问题
查看>>
[转载]struts超简单入门(三)
查看>>
[转载]JDBC编程基础
查看>>
[转载]Java手机游戏编程之MIDP图形设计篇
查看>>
[转载]Java Servlets编程指南(十八)
查看>>
[转载]实例分析J2ME网络编程的两种方法
查看>>
DNS配置全文(转)
查看>>
BIND 9快速安装实例(转)
查看>>
网站综合实例(转)
查看>>
程序界的高手传奇(转)
查看>>
CVS-RCS(2)(转)
查看>>
CVS-RCS(3)(转)
查看>>
CVS-RCS(5)(转)
查看>>