【问题标题】:How Do You Analyze This Sorting Algorithm's Time Complexity?您如何分析这种排序算法的时间复杂度?
【发布时间】:2021-06-20 19:09:48
【问题描述】:

TL;DR - 一种非比较排序算法,其执行时间根据数据类型中的位数进行缩放;如何正确评估 Big O 时间复杂度?

我有一个排序算法“Bitsort”,它的时间复杂度取决于被排序的数据类型中的位数,而不是被排序的列表的长度;对于长度从 2 个元素到最大可寻址大小的列表,完全排序所需的整个列表的传递次数由列表中使用的数据类型的大小决定。 bitsort 的简单版本(下面未优化但工作的代码示例)一次对列表进行 1 位排序。在现实世界中,这通常意味着 32 位系统在数据类型和待排序列表的最大长度中都有 32 位;并且 2^32 的 Log-base2 是 32。因此,可以说简单位排序的时间复杂度从 O(NB),其中 B 是位数,到 O(NLogN),因为 N 进入最大长度数组系统可以处理。但是,从绝对意义上讲,随着 N 趋于无穷大,B 保持不变,因此可以说时间复杂度为 O(N)。

应该如何评估简单位排序的时间复杂度?

import sys
from random import randrange

def checkOrder(arr):
    for i in range(1, len(arr)):
        if arr[i - 1] > arr[i]:
            return False
    return True


def randomArray(length, height):
    result = []
    for i in range(0, length):
        result.append(randrange(0, height, 1))
    return result


def swap(arr, left, right):
    temp = arr[left]
    arr[left] = arr[right]
    arr[right] = temp
    

# pat. pending, but not a troll
def bitsort(arr, begin, end, shiftBit):
    if end-begin <= 0 or shiftBit < 0:
        return
    LP, RP = begin - 1, end + 1
    mask = 0b1 << shiftBit

    while True:
        LP += 1
        if LP > end:
            bitsort(arr, begin, end, shiftBit - 1)
            return
        elif LP == RP:
            if LP <= begin: # left has 0 or 1 el
                pass
            else: 
                bitsort(arr, begin, LP - 1, shiftBit - 1)
            if RP >= end: # right has 0 or 1 elements
                pass
            else: 
                bitsort(arr, RP, end, shiftBit - 1) 
            return
        if arr[LP] & mask == 0:
            continue
        else:
            while True:
                RP -= 1
                if RP < begin:
                    bitsort(arr, begin, end, shiftBit - 1)
                    return
                elif LP == RP:
                    if LP <= begin:  
                        if RP <= end:
                            bitsort(arr, begin, end, shiftBit - 1)
                            return
                        else:
                            pass
                    else:  
                        bitsort(arr, begin, LP - 1, shiftBit - 1) 
                    if RP >= end:  
                        pass
                    else:  
                        bitsort(arr, RP, end, shiftBit - 1) 
                    return
                if (arr[RP] & mask) >> shiftBit == 1:
                    continue
                else:
                    swap(arr, LP, RP)
                    break


def main(args):
    arr = randomArray(1000000, 2147483648)
    bitsort(arr, 0, len(arr) - 1, 31)
    print(f'Proper order: {checkOrder(arr)}')


if __name__ == '__main__':
    main(sys.argv[1:])

【问题讨论】:

    标签: sorting big-o


    【解决方案1】:

    我会相信您的分析是正确的,并且作为 N 和 B 的函数所做的工作是 O(NB),然后专注于您的问题,即如何将其与 O 进行比较(N log N)。

    分析此类排序算法时的典型惯例是——至少从 CS 理论的角度来看——是将其分类为 O(NB) 而不是 O(N log N) 或 O(N)。原因如下:

    1. 假设您正在对一个数字列表进行排序,这些数字您知道其中没有很多位(例如,可能是美国电话区号或美国邮政编码,它们最多有 10 位长)。在这种情况下,您可以将算法调整为仅对每个数字的前十位起作用,从而减少对所有内容进行排序所需的通过次数。 O(NB) 的运行时间更清楚地表明了这一点,因为 B 减少了运行时间相应地下降。

    2. 虽然我们目前使用的机器字长通常为 32 或 64,但原则上,如果我们愿意,我们可以将字长调大。例如,SIMD 指令允许在比这更多的位上进行并行操作。或者您可能正在对变长整数进行排序,就像您对 RSA 密钥所做的那样。在这种情况下,我们不一定声称运行时间是 O(N log N),因为我们不能保证 B = O(log N)。在后一种情况下,说运行时间是 O(N) 也是不正确的,因为我们不能假装 B 是一个常数。

    3. 显式写出 O(NB) 允许我们将此排序算法与其他整数排序算法进行比较。例如,我们有运行时间为 O(N log B) 和 O(N log N / log B) 的排序算法。保留 B 项可以更轻松地查看这些其他算法与您的算法相比如何。

    4. O(N log N) 的运行时间对于大 B 和小得多的 N 来说是不正确的。在这种情况下,您可能会执行超过 O(log N) 轮位排序例程。

    【讨论】:

    • 感谢您如此中肯的回应。 1) 我同意 O(NB) 是一种更清晰的沟通方式。 2) 在实际应用中,B 的最大可能大小是否令人惊讶?我没有考虑过这种可能性。 3)我担心你使用了“整数排序算法”这个词;我的研究表明,浮点数的当前实现将按与整数相同的位显着性正确排序。另外,您能否指定其中一些其他算法;它们是 O(1) 空间吗? 4) 也许 O(NLog[Nmax])?
    • 在实践中你可能不会对 B 感到“惊讶”,因为你会提前知道你正在分类什么样的东西。术语“整数排序算法”是这类算法的通用理论术语,尽管正如您所指出的,您经常可以使用它们对浮点数进行排序。那些其他算法很重要——第一个使用 y-fast trie 数据结构,第二个使用融合树。它们不使用 O(1) 空间。
    • 再次感谢 templatetypedef 。如果您有兴趣了解复杂的 Bitsort,请告诉我。复杂(常规?)位排序可以在 9 遍中对 64 位数据类型列表进行排序;它一次按多个位排序,而不仅仅是 1。
    猜你喜欢
    • 2017-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-28
    相关资源
    最近更新 更多