C++
$\color{#cc33ff}{— > 算法基础课题解}$
$\color{gold}{— > 蓝桥杯辅导课题解}$
思路:
归并排序
$模板题$
$归并排序:$
$1、[L, R] => [L, mid], [mid + 1, r]$
$2、递归排序[L, mid]和 [mid + 1, r]$
$3、归并,将左右两个有序序列合并成一个有序序列$
时间复杂度: $O(nlog_2n)$
$code1:$
#include<iostream>
using namespace std;
const int N = 1e6 + 10;
int n, q[N], tmp[N];
void merge_sort (int q[], int l, int r){
//分治 思想
if (l >= r) return ; // 如果区间里面元素个数是1个或者没有的话,返回
//确定分界点
int mid = l + r >> 1; // 位运算 相当于 (l + r)/ 2
merge_sort(q, l, mid), merge_sort(q, mid + 1, r); // 排 左边和右边
//归并
int k = 0, i = l, j = mid + 1; // i 指向左边的起点 j 指向右边的起点
while (i <= mid && j <= r){ // i 小于左边的边界 j 小于右边的边界
if (q[i] < q[j]) tmp[k ++] = q[i ++]; // 将左右两边小的那一个数存入辅助数组tmp中
else tmp[k ++] = q[j ++];
}
while (i <= mid) tmp[k ++] = q[i ++]; // 如果左边没有循环完,把左边剩余的数存入 tmp数组
while (j <= r) tmp[k ++] = q[j ++]; // 如果左边没有循环完,把左边剩余的数存入 tmp数组
// 最后把排好序的数放回 原数组 q 中
for (int i = l, j = 0; i <= r; i ++, j ++) q[i] = tmp[j];
}
int main(){
scanf("%d", &n);
for (int i = 0; i < n; i ++) scanf("%d", &q[i]);
merge_sort(q, 0, n - 1);
for (int i = 0; i < n; i ++) printf("%d ", q[i]);
return 0;
}
$code2:$
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e5 + 10;
int n;
int q[N], tmp[N];
void merge_sort(int l, int r) { // 归并排序
if (l >= r) return;
int mid = l + r >> 1;
merge_sort(l, mid), merge_sort(mid + 1, r);
int k = 0, i = l, j = mid + 1;
while (i <= mid && j <= r) {
if (q[i] < q[j]) tmp[k ++] = q[i ++];
else tmp[k ++] = q[j ++];
}
while (i <= mid) tmp[k ++] = q[i ++];
while (j <= r) tmp[k ++] = q[j ++];
for (int i = l, j = 0; i <= r; i ++, j ++) q[i] = tmp[j];
}
int main() {
cin >> n;
for (int i = 0; i < n; i ++) cin >> q[i];
merge_sort(0, n - 1);
for (int i = 0; i < n; i ++) cout << q[i] << ' ';
return 0;
}
想问下,这个归并排序中,merge_sort(l, mid), merge_sort(mid + 1, r);这里是怎么递归让左右两边能够排好序的呀
1、将待排序的线性表不断地切分成若干个子表,直到每个子表只包含一个元素,这时,可以认为只包含一个元素的子表是有序表。
2、将子表两两合并,每合并一次,就会产生一个新的且更长的有序表,重复这一步骤,直到最后只剩下一个子表,这个子表就是排好序的线性表。
y总说,merge_sort(l, mid), merge_sort(mid + 1, r);经过后就能得到左右两段都是从小到大排序的数组,但是实际上,是不是merge_sort(l, mid), merge_sort(mid + 1, r);这两个函数只进行把他们全分成长度为一的数组,而并没有实现排序呢?而实际的过程是下面的合并的过程实现的?还是说,其实这一段merge_sort(l, mid), merge_sort(mid + 1, r);把它们分割成每段长度为的数组的过程的同时也进行着排序呢?(昨天刚开始算法基础课……对此一窍不通,可能我说的非常乱和不正确~qwq)
归并排序对序列的元素进行逐层折半分组,然后从最小分组开始比较排序,合并成一个大的分组,逐层进行,最终所有的元素都是有序的。
merge_sort(l, mid), merge_sort(mid + 1, r)实现的就是逐层折半分组,然后在回溯:从最小分组开始比较排序,合并成一个大的分组。
奥奥,谢谢~~
orz