POJ 2299 Ultra-QuickSort (归并排序求逆序对数)

  这题是要求冒泡排序交换的次数,数据这么大,直接冒泡排序肯定超时,这题实际就是求逆序对数,可以用归并排序来求逆序对数,

只需要在代码注视处加上cnt+=m-p就可以了。

  
    
// 归并排序求逆序对数
#include < iostream >
using namespace std;
int cnt = 0 ;
// 归并排序中的合并算法
void Merge( int a[], int left, int center, int len)
{
int * t = ( int * ) malloc((len - left + 1 ) * sizeof ( int )); // 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
int i = left;
int j = center;
int k = 0 ;
while (i < center && j < len) // 比较两个指针所 指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
{
if (a[i] <= a[j])
t[k
++ ] = a[i ++ ];
else
   {
    t[k
++ ] = a[j ++ ];
    
// 如果后面的数要前移,说明前半部分的后面的数原先是大于后半部分的那个数的,等于center-i,
    
// 因为每部分数组是有序的。
    cnt += center - i;
   }
}
while (i < center) // 若第一个序列有剩余,直接拷贝出来粘到合并序列尾
t[k ++ ] = a[i ++ ];
while (j < len) // 若第二个序列有剩余,直接拷贝出来粘到合并序列尾
    t[k ++ ] = a[j ++ ];

// 将排序好的序列拷贝回数组中
for (i = left,k = 0 ; i < len; i ++ ,k ++ )
a[i]
= t[k];

free(t);
}


// 归并排序
void MSort( int a[], int left, int right)
{
if (left < right)
{
int center = (left + right) / 2 ;
// 对前半部分进行排序
   MSort(a, left, center);
  
// 对后半部分进行排序
MSort(a, center + 1 , right);
  
// 合并前后两部分
Merge(a, left, center + 1 , right + 1 );
}
}

void MergeSort( int a[], int n)
{
MSort(a,
0 , n - 1 );
// =================================
for ( int i = 0 ;i < n;i ++ )
{
if (i % 5 == 0 )
cout
<< endl;
cout
<< a[i] << " " ;
}
cout
<< endl;
}

int main()
{
FILE
* fin = fopen( " 8.1.2.txt " , " r " );
int num[ 80 ],i = 0 ;
while (fscanf(fin, " %d " , & num[i]) != EOF)
i
++ ;
MergeSort(num,i);
cout
<< cnt << endl;
fclose(fin);
return 0 ;
}

 

你可能感兴趣的:(Quicksort)