【问题标题】:Finding no. of shifts in Insertion sort for large inputs in C找不到。 C 中大输入的插入排序的变化
【发布时间】:2014-09-14 13:44:02
【问题描述】:

我正在尝试编写一个程序来计算插入排序进行的交换次数。我的程序适用于小输入,但在大输入上会产生错误的答案。我也不确定如何使用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;
  }

【问题讨论】:

  • 你的 int 溢出了吗?
  • @GradyPlayer 是的,在第一种情况下,输入数量为 65911,在第三种情况下,输入 100,000 个。如果不使用 long,它会为小值提供正确的输出,当我使用 long int 时,它是也没有为小值提供正确的输出。例如:将输入作为 1 5 2 1 3 1 2 当我使用此代码时其输出为 4,当我使用 long 时其输出为 10

标签: c sorting insertion-sort


【解决方案1】:

我目前看到您的解决方案存在两个问题。

首先,cmets 提出了一个关于整数溢出的问题。在大多数系统上,int 类型最多可以容纳 231 - 1 个数字。在插入排序中,在最坏情况下需要对长度为 n 的数组进行交换的次数是n(n - 1) / 2(稍后详述),因此对于大小为 217 的数组,您最终可能无法在 int 中存储所需的交换数量.要解决这个问题,请考虑使用更大的整数类型。例如,uint64_t 类型可以存储大约 1018 的数字,这应该足以存储长度大约为 109 的数组的答案。您提到您不确定如何使用它,但好消息是它并不难。只需添加一行

#include <stdint.h>

(对于 C)或

#include <cstdint>

(对于 C++)到程序的顶部。之后,您应该能够使用uint64_t 代替int 而无需进行任何其他修改,并且一切正常。

接下来是效率问题。您发布的代码基本上运行插入排序,因此在最坏的情况下需要时间 O(n2) 。对于大型输入 - 例如,大小为 108 的输入 - 这非常昂贵。不过令人惊讶的是,您实际上可以确定插入排序将产生多少交换,而无需实际运行插入排序。

在插入排序中,交换的次数等于输入数组中存在的inversions 的数量(反转是一对无序的元素)。有一个beautiful divide-and-conquer algorithm for counting inversions 运行时间为 O(n log n),它可能会扩展到处理比仅运行插入排序更大的输入。我认为这个问题的“最佳”答案是使用这个算法,同时注意使用uint64_t 类型或类似的其他类型,因为它会使你的算法在更大的输入上正常工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-11
    • 2013-04-04
    • 2012-12-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多