一、冒泡排序
简单来说,它就是重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。
#include<iostream>
#include<vector>
void bubbleSort(std::vector<int>& arr) {
auto n = arr.size();
for (auto i = 0; i < n - 1; ++i) {
for (auto j = 0; j < n - 1 - i; ++j) {
if (arr[j] > arr[j + 1]) {
std::swap(arr[j], arr[j + 1]);
}
}
}
}
int main() {
std::vector<int> vec{ 2, 6, 7, 8, 4 };
bubbleSort(vec);
for (auto& v : vec) {
std::cout << v << ' ';
}
std::cout << std::endl;
return 0;
}
- 优化冒泡排序算法如下
void bubblesort(int a[], const int& n){
bool sorted = false; // 整体排序标志,这是本算法的有力手段
while(!sorted){
sorted = true; // 假定已经排序
for(int i = 1; i < n; ++i){ // 自左向右逐对检查当前范围 a[0, n)内的各相邻元素
if(a[i - 1] > a[i]){ // 逆序则交换
std::swap(a[i - 1], a[i]);
sorted = false; // 因整体排序不能保证,需要清除排序标志位
}
}
n--; // 至此末元素必然就位,故可以缩短待排序序列的有效长度
}
}
☆ 借助布尔型标志位 sorted,可以提前退出,而不总是蛮力地做 n - 1趟扫描交换。
时间复杂度: O(n^2)
空间复杂度:O(1)
稳定
二、插入排序
插入排序,一般也被称为直接插入排序。对于少量元素的排序,它是一个有效的算法 。插入排序是一种最简单的排序方法,它的基本思想是将一个记录插入到已经排好序的有序表中,从而一个新的、记录数增 1 的有序表。在其实现过程使用双层循环,外层循环对除了第一个元素之外的所有元素,内层循环对当前元素前面有序表进行待插入位置查找,并进行移动。
#include<iostream>
#include<vector>
void insertSort(std::vector<int>& arr) {
auto n = arr.size();
for (auto i = 0; i < n; ++i) {
// 寻找插入位置
for (auto j = i; j > 0; --j) {
if (arr[j] < arr[j - 1]) {
std::swap(arr[j], arr[j - 1]);
}
}
}
}
int main() {
std::vector<int> vec{ 2, 6, 7, 8, 4 };
insertSort(vec);
for (auto& v : vec) {
std::cout << v << ' ';
}
std::cout << std::endl;
return 0;
}
时间复杂度: O(n^2)
空间复杂度:O(1)
稳定
三、选择排序
选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。选择排序是不稳定的排序方法。
#include<iostream>
#include<vector>
void selectSort(std::vector<int>& arr) {
auto n = arr.size();
for (auto i = 0; i < n; ++i) {
auto minIndex = i; // 将待排序元素中的最小值和排好序的后一个元素交换位置
for (auto j = i + 1; j < n; ++j) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
std::swap(arr[minIndex], arr[i]);
}
}
}
}
int main() {
std::vector<int> vec{ 2, 6, 7, 8, 4 };
selectSort(vec);
for (auto& v : vec) {
std::cout << v << ' ';
}
std::cout << std::endl;
return 0;
}
时间复杂度: O(n^2)
空间复杂度:O(1)
不稳定