前言:
脱更5个月的小编回来啦!这段时间小编一直都在摆烂,相比上学期小编似乎丧失了学习的动力,从今天起小编将重拾信心与动力,持续更新,小编将会用一个月的时间更新算法入门系列。今天我要分享的是算法入门之排序与查找(归并排序)。
归并排序的主要思想是分治算法与合并,首先介绍一下分治算法,将一个复杂的问题分为几个简单的小问题,解决局部问题最后合并答案解决复杂问题。分治法是归并排序的主要思路,首先将要排序的数组分为尽量相等长的两部分,紧接又继续往下分,一直分到一个数组里有一个元素即可(采用递归),因为每一个元素都自带有序性,然后就是合并了,合并的过程就是一种排序。合并也是归并排序的精髓所在。
以下我将具体介绍思路:假设有一个长度为5的数组,里面元素有5,9,12,1,4;首先我们要获取两个边界,左边界和右边界确定分割线,然后递推下去。
以上便是归并排序。
代码如下:
//归并排序
void merge_sort(int* A, int x, int y, int* T){
if(y - x > 1){
int m = x + (y - x) / 2;
int p = x , q = m , i = x; // 用指针控制各个部分起始位置
merge_sort(A, x,m , T); // [x,m)左半部分
merge_sort(A, m, y, T); // [m,y)右半部分
while(p < m || q < y){ // 如果左半部分或右半部分元素没有合并完成则继续
if (q >= y || (p < m && A[p] < A[q])) // 比较左半区和右半区的元素大小
T[i++] = A[p++]; // 将小的元素(左半部分小的和右半部分比左半部分小的)元素加到辅助数组里边
else{
T[i++] = A[q++]; // 否则将大的元素加到辅助数组里面
}
}
for(int j = x; j < i ; j++)
A[j] = T[j];
}
}
int main(){
int n;
cin >> n;
vector<int> a(n);
vector<int> t(n);
for(int i = 0; i < n; ++i){
cin >> a[i];
}
merge_sort(a.data(),0,n,t.data());
for(int i = 0; i < n; ++i){
cout << a[i] << " ";
}
return 0;
}
接下来我们要解决逆序列的个数问题,什么是逆序列呢?
问题描述:
逆序对问题。给一列数a1 , a2 , … , an,求它的逆序对数,即有多少个有序对(i,j),使
得
i
<
j
但
a
i
>
a
j
。
我们不难发现,归并排序每一次排序就是一次逆序重组,我们只要加入一个计数器,而每一次重新排序的时候,还未加入到辅助数组里的元素m-p个都比辅助数组里的元素大,所以只要连加m-p就可以。
以下是代码:
//归并排序
int merge_sort(int* A, int x, int y, int* T){
int cnt = 0;
if(y - x > 1){
int m = x + (y - x) / 2;
int p = x , q = m , i = x; // 用指针控制各个部分起始位置
merge_sort(A, x,m , T); // [x,m)左半部分
merge_sort(A, m, y, T); // [m,y)右半部分
while(p < m || q < y){ // 如果左半部分或右半部分元素没有合并完成则继续
if (q >= y || (p < m && A[p] < A[q])) // 如果 q >= y,意味着右半部分的数组元素已经全部放入了辅助数组中,此时不管左半部分是否还有剩余元素,都会将左半部分的元素加入到辅助数组中。
T[i++] = A[p++]; // 左右两部分数组都还有剩余元素,此时会比较左右两部分当前元素的大小,如果 A[p] < A[q],则将左半部分的元素加入到辅助数组中;
else{
T[i++] = A[q++]; // 否则将右半部分元素直接加入辅助数组中
cnt += m - p;
}
}
for(int j = x; j < i ; j++)
A[j] = T[j];
}
return cnt;
}
int main(){
int n;
cin >> n;
vector<int> a(n);
vector<int> t(n);
for(int i = 0; i < n; ++i){
cin >> a[i];
}
cout << merge_sort(a.data(),0,n,t.data());
// for(int i = 0; i < n; ++i){
// cout << a[i] << " ";
// }
return 0;
}