我试图编写一个程序来计算插入排序所产生的掉期数量。我的程序适用于小输入,但在大输入上产生错误的答案。我还不确定如何使用long int
类型。
此问题出现在https://drive.google.com/file/d/0BxOMrMV58jtmNF9EcUNQNGpreDQ/edit?usp=sharing
中描述的设置中输入为
The first line contains the number of test cases T. T test cases follow.
The first line for each case contains N, the number of elements to be sorted.
The next line contains N integers a[1],a[2]...,a[N].
我使用的代码是
#include <stdio.h>
#include <stdlib.h>
int insertionSort(int ar_size,int * ar)
{
int i,j,t,temp,count;
count=0;
int n=ar_size;
for(i=0;i<n-1;i++)
{
j=i;
while(ar[j+1]<ar[j])
{
temp=ar[j+1];
ar[j+1]=ar[j];
ar[j]=temp;
j--;
count++;
}
}
return count;
}
int main()
{
int _ar_size,tc,i,_ar_i;
scanf("%d", &tc);
int sum=0;
for(i=0;i<tc;i++)
{
scanf("%d", &_ar_size);
int *_ar;
_ar=(int *)malloc(sizeof(int)*_ar_size);
for(_ar_i = 0; _ar_i < _ar_size; _ar_i++)
{
scanf("%d", &_ar[_ar_i]);
}
sum=insertionSort(_ar_size, _ar);
printf("%d\n",sum);
}
return 0;
}
答案 0 :(得分:0)
我目前看到的解决方案有两个问题。
首先,关于整数溢出的注释中出现了一个问题。在大多数系统中,int
类型可以将数字保持为2 31 - 1.在插入排序中,在最坏情况下需要在长度数组上进行交换的数量n是n(n - 1)/ 2(稍后详述),因此对于大小为2 17 的数组,您可能最终无法在{I}中存储所需的交换数量{1}}。要解决此问题,请考虑使用更大的整数类型。例如,int
类型可以存储大约10 18 的数字,这应该足以存储长度大约10 9 的数组的答案。 。你提到你不确定如何使用它,但好消息是它并不那么难。只需添加一行
uint64_t
(对于C)或
#include <stdint.h>
(对于C ++)到程序的顶部。在那之后,您应该能够使用#include <cstdint>
代替uint64_t
而无需进行任何其他修改,一切都应该正常运行。
接下来,存在效率问题。您发布的代码基本上运行插入排序,因此在最坏情况下需要时间O(n 2 )。对于大输入 - 比如大约10 8 的输入 - 这是非常昂贵的。但令人惊讶的是,您实际上可以确定在没有实际运行插入排序的情况下插入排序的次数。
在插入排序中,交换次数等于输入数组中存在的inversions的数量(反转是一对乱序的元素)。有一个beautiful divide-and-conquer algorithm for counting inversions在时间O(n log n)运行,它可能会扩展到比仅运行插入排序更大的输入。我认为最好的&#34;回答这个问题就是使用这个算法,同时注意使用int
类型或类似的其他类型,因为它会使你的算法在更大的输入上正常工作。