归并排序
具体可见《算法导论》——分治法。下例为POJ上2299题,用的是归并法求逆序数的个数:
/**
题目的意思就是要求冒泡排序的交换次数。
所用的算法:用归并排序,求逆序数的个数。
##这道题充分印证了,即使merge本身可能用的不多,但分冶的思想却是无所不在
**/
#include <stdio.h>
int left[250003], right[250003];
long long count;
void merge(int* a, int p, int q, int r)
{
int i, j, k, n1, n2;
n1 = q-p+1;
n2 = r-q;
for (i=0; i<n1; i++)
{
left[i] = a[p+i];
}
for (i=0; i<n2; i++)
{
right[i] = a[q+i+1];
}
left[n1] = right[n2] = 0x7fffffff;
i = j = 0;
for (k=p; k<=r; k++)
{
if (left[i] <= right[j])
{
a[k] = left[i];
i++;
}
else
{
a[k] = right[j];
j++;
count += n1-i; /**此步骤是在归并排序法中加的一句,用来计数求逆序数的数目**/
}
}
return;
}
void mergesort(int* a, int p, int r)
{
int q;
if (p < r)
{
q = (p+r)/2;
mergesort(a, p, q);
mergesort(a, q+1, r);
merge(a, p, q, r);
}
return ;
}
int main()
{
int n, i, a[500001];
while (scanf("%d", &n) && n)
{
count = 0;
for (i=0; i<n; i++)
{
scanf("%d", &a[i]);
}
mergesort(a, 0, n-1);
printf("%lld/n", count);
}
}