两种排序
一、快速排序
//快速排序
void quick_sort(int a[],int l,int r)
{
if( l >= r ) return;
int i = l - 1, j = r + 1, x = a[l + r >> 1];// x表示中间值 l + r >> 1 == (l + r) /2;
while( i < j )
{
do i++ ;while( a[i] < x );
do j++ ;while( a[j] > x );
if( i < j )swap(a[i],a[j]);
}
quick_sort(a,l,j), quick_sort(a,j + 1,r);//对分开的俩块分别进行排序即可
}
- 类似于双指针算法
- 1.如果
a[i] < x
则循环继续 若不成立 do i++ 停止执行 直到 2 停止时if( i < j )swap(a[i],a[j]); 继续执行代码
- 2.如果
a[j] > x
则循环继续 若不成立 do j++ 停止执行 直到 1 停止时if( i < j )swap(a[i],a[j]); 继续执行代码
二、归并排序
//归并排序
void merge_sort(int a[],int l, int r)
{
if( l >= r ) return;
int mid = l + r >> 1;//分治
merge_sort(a,l,mid) , merge_sort(a,mid+1,r);//递归处理子问题
int i = l, j = mid + 1,k = 0;
while( i <= mid && j <= r )
{
if( a[i] >= a[j] ) t[k++] = a[j++];
else t[k++] = a[i++];
}
while( i <= mid ) t[k++] = a[i++];//两个 while 中 必有一个是不成立的
while( j <= r ) t[k++] = a[j++];
for( int i = l,j = 0; i <= r; i++ )
a[i] = t[j++]; //将临时数组的值赋值回到原数组
}
- 为什么不用 mid - 1 作为分隔线呢
即 merge_sort(q, l, mid - 1 ), merge_sort(q, mid, r)
因为 mid = l + r >> 1 是向下取整,mid 有可能取到 l (数组只有两个数时),造成无限划分
解决办法: mid 向上取整就可以了, 即 mid = l + r + 1 >> 1
三、逆序对数量(归并排序解决)
//逆序对的个数(归并排序
long long merge_sort_2(int a[],int l, int r)
{
//int ans = 0;
if( l >= r ) return 0;
int mid = l + r >> 1;
long long ans = merge_sort_2(a,l,mid) + merge_sort_2(a,mid+1,r);
int i = l, j = mid + 1,k = 0;
while( i <= mid && j <= r )
if( a[i] > a[j] )
{
t[k++] = a[j++];
ans += mid - i + 1;
}
else
t[k++] = a[i++];
while( i <= mid ) t[k++] = a[i++];
while( j <= r ) t[k++] = a[j++];
for( int i = l,j = 0; i <= r; i++ )
a[i] = t[j++];
return ans;
}
- 此处要使用long long 定义函数类型,因为返回的逆序对数量是一个整数,而且有可能很大