ps:排序算法是否稳定的依据:相同数值的数字在排序后的相对位置是否跟原来一样
归并排序,先利用递归,以中点分界,排成两段有序序列。
然后用双指针算法,分别对这两段序列从头到尾遍历,并且每一个做对比,把小的放入新的一个数组里面。合二为一,最后把临时数组的数据拷贝回原来的数组,完成归并排序。
时间复杂度 O(nlogn),空间复杂度(n);
#include <bits/stdc++.h>
using namespace std;
vector<int> temp(1e5 + 10);
void merge_sort(vector<int> &q, int left, int right) {
if (left >= right) return;
int mid = left + (right - left) / 2;
merge_sort(q, left, mid);
merge_sort(q, mid + 1, right);
int i = left, j = mid + 1;
int k = 0;
while (i <= mid && j <= right) {
if (q[i] > q[j]) temp[k++] = q[j++];
else temp[k++] = q[i++];
}
while (i <= mid) temp[k++] = q[i++];
while (j <= right) temp[k++] = q[j++];
for (i = left, j = 0; i <= right; i++, j++) q[i] = temp[j];
}
int main() {
int n;
cin >> n;
vector<int> q(n);
for (auto &x : q) cin >> x;
merge_sort(q, 0, n - 1);
for (auto x : q) cout << x << " ";
cout << endl;
return 0;
}
快速排序
对于一段乱序数组,可以随机选取一个值,一般选中间点作为基准值。
然后分别用双指针算法在头跟尾各自往中间扫描,遇到不合适的条件时,停下来,交换。目的是为了让基准值左边的数都小于基准值,让基准值右边的数都大于基准值。然后再递归处理。完成快排。
时间复杂度O(nlogn), 空间复杂度(logn);
#include <bits/stdc++.h>
using namespace std;
void quick_sort(vector<int> &q, int left, int right) {
if (left >= right) return;
int i = left - 1, j = right + 1;
int mid = left + (right - left) / 2;
int midVal = q[mid];
//中间点可以任意取,但是下面递归边界写的是j和j + 1,这里就不能取q[r]
//反之如果下面递归取的是i-1和i,这里就不能取q[l],否则会发生无限递归,如数组1,2,(会有一个递归区间无限重复循环)
while (i < j) {
while (q[++i] < midVal);
while (q[--j] > midVal);
if (i < j) swap(q[i], q[j]);
}
quick_sort(q, left, j);
quick_sort(q, j + 1, right);
}
int main() {
int n;
cin >> n;
vector<int> q(n);
for (auto &x : q) cin >> x;
quick_sort(q, 0, n - 1);
for (auto x : q) cout << x << " ";
cout << endl;
return 0;
}