【问题标题】:Measuring time complexity of some sorting algorithms测量一些排序算法的时间复杂度
【发布时间】:2015-02-28 23:58:47
【问题描述】:

我正在用Java编写一个演示类来分析以下排序算法:

  1. 插入排序
  2. 选择排序
  3. 冒泡排序
  4. 合并排序
  5. 快速排序

我已经在另一个名为 Sort 的类中实现了静态方法。

我想通过使用 omicron 公式确定运行时间和分析复杂性来比较每种算法的最佳、平均和最坏情况。

在演示类中,我只想确定每个算法需要以最佳、平均和最坏情况的数组中数字的顺序对具有不同长度的整数数组进行排序的时间(以纳秒为单位)。

        //Best-Case
    int[] arrbc0 = {1};
    int[] arrbc1 = {1, 2};
    int[] arrbc2 = {1, 2, 3};
    int[] arrbc3 = {1, 2, 3, 4, 5};
    int[] arrbc4 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int[] arrbc5 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};

    //Average-Case
    int[] arrac1 = {1, 2};
    int[] arrac2 = {3, 1, 2};
    int[] arrac3 = {4, 2, 3, 1, 5};
    int[] arrac4 = {9, 1, 10, 6, 2, 4, 8, 3, 7, 5};
    int[] arrac5 = {13, 12, 1, 15, 5, 6, 7, 2, 14, 10, 3, 8, 4, 9, 11};

    //Worst-Case
    int[] arrwc1 = {2, 1};
    int[] arrwc2 = {3, 2, 1};
    int[] arrwc3 = {5, 4, 3, 2, 1};
    int[] arrwc4 = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
    int[] arrwc5 = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1};

    //InsertionSort:
    isNanoTime(arrbc0); //first load
    isNanoTime(arrbc1);
    isNanoTime(arrbc2);
    //...

    public static void isNanoTime(int[] arr) {
    long a1 = System.nanoTime();
    Sort.insertionSort(arr);
    long a2 = System.nanoTime() - a1;
    System.out.println(a2);
    }

现在我有一些问题:

  1. 我能否将这些数组用于这些算法的所有最佳、平均和最坏情况,或者有 f.e. MergeSort 另一个订单的最坏情况?!
  2. 有没有一种简单的方法可以在对数组进行一次排序后取消排序?
  3. 这是否是确定时间复杂度的“正确方法”(也许有人有更好的主意)?

【问题讨论】:

  • 它可以(某种程度上)展示时间复杂度,但我认为它不能确定它。执行时间和时间复杂度是相关的,但是不同的动物。
  • 这将是一个艰难的原因有很多原因,尤其是stackoverflow.com/questions/504103/…

标签: java arrays algorithm sorting time-complexity


【解决方案1】:
  1. 您的数组太短了:任何“现代”CPU 几乎都不需要时间来对它们进行排序,即使在最坏的情况下也是如此
  2. 要根据输入的随机性产生相关的时间变化,您需要设置一个固定的输入大小,并为您提供可测量的时间(可能以秒为单位)
  3. 您可能需要生成一个包含数千个随机数组的集合,可能还需要向该集合添加一些特定的数组(排序的、反向排序的,...)。然后,您可以在该集合中的每个数组上运行每个算法,并测量对它们进行排序所需的时间。这样做可以为每个算法获得一个很好的分布图,在该分布图上可以看到每个算法的行为(冒泡排序非常高,而堆排序非常稳定......)。一种算法的最差输入不一定与另一种算法相同,因此是集合。

【讨论】:

    【解决方案2】:
    1. 此类数组可以展示 InsertionSort 和 BubbleSort 的最坏和最佳情况。 MergeSort 和 SelectionSort 的典型实现对所有数组具有相同的复杂性。最简单的快速排序实现的最坏情况是排序(或反向排序)数组。
      Wiki page with useful table
      请注意,这些数组太短而无法注意到运行时间的任何差异。制作包含 10^3-10^6 个元素的数组(分别用于慢速和快速算法)。

    2. 查看Fisher-Yates shuffle获取随机序列

    【讨论】:

      【解决方案3】:

      @MBo @Jean Logeart

      您对此有何看法:

      //Main:
      for(int n = 100_000; n <= 1_000_000; n = n + 100_000) {
          //f.e. average case of insertion sort:
          int[] arr = randomArray(n);
          insertionSortWithRuntime(arr);
      }
      
      /**
       * For best cases using sorted numbers.
       * @param n- the length in which the array should be created.
       * @return
       */
      public static int[] sortedArray(int n) {
          int[] arr = new int[n];
      
          for (int i = 0; i < n; i++) {
              arr[i] = i;
          }
          return arr;
      }
      
      /**
       * For average cases using random numbers.
       * @param n - the length in which the array should be created.
       * @return
       */
      public static int[] randomArray(int n) {
          int[] arr = new int[n];
      
          for (int i = 0; i < n; i++) {
              arr[i] = (int) (Math.random() * 9 + 1);
          }
          return arr;
      }
      
      /**
       * For worst cases using reversed sorted numbers.
       * @param n - the length in which the array should be created.
       * @return
       */
      public static int[] reversedSortedArray(int n) {
          int[] arr = new int[n];
      
          int length = n - 1;
      
          for (int i = 0; i < n; i++) {
              arr[i] = length;
              length--;
          }
          return arr;
      }
      

      你有没有这样想象过?

      【讨论】:

      • 我为二次算法(插入/冒泡排序)提出了太大的尺寸。大小 1000-10000 是合理的。
      • 好的,我现在用这个:for(int n = 10_000; n
      • 对于 n = 10000, 20000, 30000, 40000,您将获得 100 毫秒、400 毫秒、900 毫秒、1600 毫秒等时间 - 这是二次相关性,并且图形(时间与 N)将看起来像抛物线
      • 但是你怎么知道数组中的 10.000 个字段是大 O 表示法的 10(毫秒)的输入?那么对于 O(n),它必须是 10、20、30,但是像 100、200、300 之类的东西在这里更合适
      • 同样奇怪的是,即使在 10.000 - 1.000.000 长度的数组中,QuickSort 也不需要超过 62 毫秒?!
      猜你喜欢
      • 2015-01-05
      • 1970-01-01
      • 1970-01-01
      • 2022-12-03
      • 1970-01-01
      • 1970-01-01
      • 2017-01-24
      • 2017-05-28
      相关资源
      最近更新 更多