1、冒泡排序
冒泡排序重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
#include <iostream>
#include <vector>
using namespace std;
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++) {
if (arr[j] > arr[j + 1]) {
// 交换 arr[j] 和 arr[j+1]
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
int main() {
vector<int> arr = {64, 34, 25, 12, 22, 11, 90};
bubbleSort(arr);
cout << "Sorted array: \n";
for (int i = 0; i < arr.size(); i++) {
cout << arr[i] << " ";
}
return 0;
}
// 输出
Sorted array:
11 12 22 25 34 64 90
2、插入排序
将数组的第一个数认为是有序数组,从后往前(从前往后)扫描该有序数组,把数组中其余n-1个数,根据数值的大小,插入到有序数组中,直至数组中的所有数有序排列为止。类似与"扑克牌",从桌上抓牌,一张一张的抓,并进行比较排序。
#include <iostream>
#include <vector>
using namespace std;
void insertionSort(vector<int>& arr) {
int n = arr.size();
for (int i = 1; i < n; i++) {
int key = arr[i];
int j = i - 1;
// 将大于key的元素向后移动一位
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j = j - 1;
}
// 找到key的位置后插入
arr[j + 1] = key;
}
}
int main() {
vector<int> arr = {64, 34, 25, 12, 22, 11, 90};
insertionSort(arr);
cout << "Sorted array: \n";
for (int i = 0; i < arr.size(); i++) {
cout << arr[i] << " ";
}
return 0;
}
应用
- 小规模数据处理
当需要排序的数据量较小时,插入排序由于其简单性和低开销(尤其是空间开销)而成为一个合适的选择。例如,在嵌入式系统或资源受限的环境中,插入排序可能是首选。 - 几乎有序的数据:
如果数据已经接近有序状态,插入排序会非常高效。在这种情况下,插入排序的复杂度可以接近O(n),因为它只需要对少数元素进行调整。例如,在实时系统中处理传感器数据时,如果数据随时间变化而缓慢变化,那么插入排序可能是一个好的选择。 - 稳定性需求:
插入排序是一种稳定的排序算法,即相等的元素在排序后保持其原有的相对顺序。这在处理具有多个排序键的数据时非常重要,如按照姓名和年龄对学生进行排序。在商业应用中,如订单处理系统,稳定性可能是一个关键要求。 - 实时系统:
在需要快速响应的实时系统中,如果数据是逐步到达的,并且需要即时排序,插入排序可以很好地工作。它可以在每个新元素到达时将其插入到已排序的序列中的正确位置。 - 简单性和可维护性:
插入排序的算法逻辑相对简单直观,易于理解和实现。在开发过程中,如果需要快速实现一个排序功能,并且不需要关注性能优化,那么插入排序是一个快速且可靠的选择。
3、快速排序
通过选取一个基准值,将待排序序列分为两部分:一部分是所有小于基准值的元素,另一部分是所有大于或等于基准值的元素。然后,对这两部分递归地进行快速排序,直到整个序列有序。
#include <iostream>
#include <vector>
using namespace std;
// 快速排序函数
void quickSort(vector<int>& arr, int left, int right) {
if (left < right) {
// 分区操作,返回分区点
int pivotIndex = partition(arr, left, right);
// 递归对左侧子数组进行快速排序
quickSort(arr, left, pivotIndex - 1);
// 递归对右侧子数组进行快速排序
quickSort(arr, pivotIndex + 1, right);
}
}
// 分区操作函数
int partition(vector<int>& arr, int left, int right) {
// 选择最右侧的元素作为主元
int pivot = arr[right];
int i = left - 1; // 小于主元的元素的索引
for (int j = left; j < right; j++) {
// 如果当前元素小于或等于主元
if (arr[j] <= pivot) {
i++; // 增加小于主元的元素的索引
swap(arr[i], arr[j]); // 交换元素
}
}
// 将主元放到正确的位置上
swap(arr[i + 1], arr[right]);
return i + 1; // 返回主元的索引
}
int main() {
vector<int> arr = {64, 34, 25, 12, 22, 11, 90};
quickSort(arr, 0, arr.size() - 1);
cout << "Sorted array: \n";
for (int i = 0; i < arr.size(); i++) {
cout << arr[i] << " ";
}
return 0;
}