【问题标题】:Why is binary insertion sort faster than direct insertion sort?为什么二进制插入排序比直接插入排序快?
【发布时间】:2023-02-05 23:48:51
【问题描述】:

直接插入排序的实现:

void insertion_sort(int a[], int n) {
    for (int i = 1; i < n; i++) {
        int key = a[i];
        int j = i - 1;
        while (j >= 0 && a[j] > key) {
            a[j + 1] = a[j];
            j--;
        }
        a[j + 1] = key;
    }
}

二分插入排序的实现:

void insertion_sort(int a[], int n) {
    for (int i = 1; i < n; i++) {
        int key = a[i];
        int mid = upper_bound(a, a + i, key) - a;
        for (int j = i - 1; j >= mid; j--) a[j + 1] = a[j];
        a[mid] = key;
    }
}

网上教程说二分插入排序比直接插入排序快,因为二分查找比顺序查找快,但我不这么认为。

直接插入排序虽然采用顺序查找,但是当找到插入位置时,元素已经移动了。但是二分插入排序需要花费O(log i)的时间去寻找插入位置,而且找到之后元素还没有移动。如果只看循环内部,二分插入排序比直接插入排序耗时多O(log i),那为什么那么多人说前者比后者快呢?

【问题讨论】:

    标签: sorting binary-search insertion-sort


    【解决方案1】:

    首先,整体复杂性没有改变,因为“昂贵”的部分正在移动可能是O(n)的元素。因此整个算法仍然是O(n²)。因此,如果您查看使用渐近度量的算法,则两者之间没有区别。但是,如果您查找实际操作计数,则可以看出差异。

    显然,在这两种算法中你有相同数量的移动操作。变化的是比较操作的数量:

    • 使用二分查找你有log(n - i)比较操作
    • 使用直接插入排序,您可以在 while 循环条件中进行比较,因此您的比较操作与移动操作一样多(实际上还有一个,因为当 while 循环退出时也会检查条件),因此您可以拥有 n最坏情况下的比较操作

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-01
      • 2020-07-30
      • 1970-01-01
      • 2011-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-22
      相关资源
      最近更新 更多