十大排序算法
- 冒泡排序
从序列的一端开始往另一端冒泡,依次比较相邻的两个数的大小。代码实现如下
void sort(vector<int>& vec) {
for (int i = 0; i < vec.size() - 1; ++i) {
for (int j = 0; j < vec.size() - i - 1; ++j) {
int tem;
if (vec[j] > vec[j + 1])
swap(vec[j], vec[j + 1]);
}
}
}
时间复杂度为\(O(n^2)\),空间复杂度\(O(1)\)
还可以进一步对冒泡排序进行优化,当进行一轮交换操作之后,如果没有两个逆序对,则证明序列此时已经有序,退出循环即可。代码如下
void sort(vector<int>& vec) {
for (int i = 0; i < vec.size() - 1; ++i) {
bool flag = true;
for (int j = 0; j < vec.size() - i - 1; ++j) {
int tem;
if (vec[j] > vec[j + 1]) {
flag = false;
swap(vec[j], vec[j + 1]);
}
}
if (flag)
break;
}
}
- 选择排序
遍历数组,每次挑选出最大的放到数组末尾,代码如下
void sort(vector<int>& vec) {
for (int i = 0; i < vec.size(); ++i) {
int min = i;
for (int j = i; j < vec.size(); ++j) {
if (vec[j] < vec[min]) {
min = j;
}
}
swap(vec[i], vec[min]);
}
}
时间复杂度为\(O(n^2)\),空间复杂度\(O(1)\)
- 插入排序
void sort(vector<int>& vec) {
for (int i = 1; i < vec.size(); ++i) {
int val = vec[i];
int j;
for (j = i - 1; j >= 0; --j) {
if (vec[j] < val) {
break;
}
vec[j + 1] = vec[j];
}
vec[j + 1] = val;
}
}
下标i将数组分为两部分,i之前的数组已经有序,将vec[i]
在\([0,i-1]\)范围内寻找合适位置进行插入。时间复杂度也为\(O(n^2)\)
- 二路归并排序
void mergesort(vector<int>& arr, int left, int right) {//[left, right]
if (left >= right)
return;
int mid = (right - left) / 2 + left;
mergesort(arr, left, mid);
mergesort(arr, mid + 1, right);
merge(arr, left, mid, right);
}
void merge(vector<int>& arr, int left, int mid, int right) {
vector<int> nums(right - left + 1);
//左边有序数组的首位下标和右边有序数组的有序下标
int lo = left, hi = mid + 1;
int index = 0;
//把左部分和右部分较小的数移到数组中,当左边或右边某部分结束
while (lo <= mid && hi <= right) {
if (arr[lo] <= arr[hi])
nums[index++] = arr[lo++];
else
nums[index++] = arr[hi++];
}
//把左边数组剩余部分移动到数组中
while (lo <= mid) {
nums[index++] = arr[lo++];
}
//把右边剩余的数移入数组
while (hi <= right) {
nums[index++] = arr[hi++];
}
//将新数组的值赋给原数组
for (int i = 0; i < nums.size(); ++i) {
arr[i + left] = nums[i];
}
}
- 快速排序
未完待续...