【问题标题】:have I invented a new sorting algorithm? or is this the same as quicksort我发明了一种新的排序算法吗?或者这和快速排序一样吗
【发布时间】:2012-04-04 11:02:44
【问题描述】:

我做了一个排序算法,但后来我想也许我刚刚重新发明了快速排序。

但是我听说快速排序是 O(N^2) 最坏的情况;我认为我的算法应该只有 O(NLogN) 最坏的情况。

这和快速排序一样吗?​​

该算法通过交换值来工作,以便将所有小于中位数的值移动到数组的左侧。然后它在每一侧递归地工作。

算法从 i=0 开始,j = n-1

i 和 j 相互靠近,必要时交换 list[i] 和 list[j]。

这是递归前第一次迭代的一些代码:

_list = [1,-4,2,-5,3,-6]

def in_place(_list,i,j,median):
    while i<j:
        a,b = _list[i],_list[j]
        if (a<median and b>=median):
            i+=1
            j-=1
        elif (a>=median and b<median):
            _list[i],_list[j]=b,a
            i+=1
            j-=1
        elif a<median:
            i+=1
        else:
            j-=1
    print "changed to ", _list



def get_median(_list):
    #approximate median in O(N) with O(1) space
    return -4

median = get_median(_list)
in_place(_list,0,len(_list)-1,median)

"""
changed1 to  [-6, -5, 2, -4, 3, 1]
"""

【问题讨论】:

  • IIUC get_median 被调用大约 log(N) 次。在那种情况下,您的算法类似于快速排序(“pivot”)(但我不懂 Python)
  • 我刚看到 TimSort。它使用“运行”。也许这也可以优化为使用运行。

标签: algorithm sorting quicksort in-place


【解决方案1】:

http://en.wikipedia.org/wiki/Quicksort#Selection-based_pivoting

相反,一旦我们知道最坏情况的 O(n) 选择算法是 可用,我们可以使用它在每个位置找到理想的枢轴(中位数) 快速排序步骤,产生最坏情况 O(n log n) 的变体 运行时间。然而,在实际实现中,这种变体是 平均速度要慢得多。

另一种变体是选择中位数的中位数作为枢轴 元素而不是中位数本身来划分元素。 在保持渐近最优运行时间复杂度的同时 O(n log n) (通过防止最坏情况的分区),它也是 比选择中值作为枢轴的变体快得多。

【讨论】:

  • 虽然我同意这不是一种新算法,甚至不是一种新的枢轴选择方法,但我认为三的中位数与 n 的中位数不同。特别是,我认为 n 枢轴选择的中位数与 3 路分区(他没有提到/显示)相结合,实际上可以保证 O(n*log n)。
  • Karoly,所以你说的是这种快速排序的变体是 O(NLogN) 而不是 O(N^2),因为我的算法可能不是 O (N^2) 并不意味着它不是快速排序..
  • 是的。是和不是。它是它的一个变种。不是经典的快速排序。
【解决方案2】:

对于初学者,我假设没有显示其他代码,因为我很确定您自己显示的代码不会工作。

很抱歉偷了你的火,但我担心你显示的代码似乎是快速排序,不仅如此,而且代码似乎可能存在一些错误。

考虑对相同元素列表进行排序的情况。您的 _in_place 方法(这似乎是 Quicksort 中传统上称为分区的方法)不会正确移动任何元素,但最后 ji 似乎反映了列表只有一个分区包含整个列表,在这种情况下,您将永远在整个列表上再次递归。如前所述,我的猜测是,您不会从中返回任何内容,或者似乎实际上在任何地方都已完全排序,所以我只能猜测如何使用它。

恐怕使用快速排序的实际中位数不仅在一般情况下可能是一个相当慢的策略,它也不能避免 O(n^2) 最坏的情况,同样的元素列表将提供这种最坏的情况。但是,我认为具有这种中值选择算法的三路分区快速排序将保证 O(n*log n) 时间。尽管如此,这是枢轴选择的已知选项,而不是新算法。

简而言之,这似乎是一个不完整且可能存在错误的快速排序,并且如果没有三向分区,使用中位数将无法保证 O(n*log n)。但是,我确实觉得这是一件好事,值得祝贺你自己想到了使用中位数的想法——即使其他人之前已经想到过。

【讨论】:

  • 我认为所有元素都是平等的问题可以用if (a&lt;=median and b&gt;=median) i+=1 j-=1解决
  • 我可能错了,但我在他的代码中的任何地方都看不到 - 有 a,以及 a=。我认为这种情况只是 j-=1。
  • 感谢您的回复。我只是认为这可能与快速排序不同,因为它只交换值,快速排序将枢轴从右侧移到中间。只要可以修复错误,我就不太担心。我认为如果所有元素都相等,则 j 变为 0,并且在这种情况下您可以有逻辑选择不递归(通过将 j 与原始 i 进行比较)。我使用中位数的唯一原因是尝试使前两个分区更大,尽管稍后可能有一种很好的方法来近似每个分区的中位数。
  • @KarolyHorvath:我很抱歉,我没有注意到你的意思是添加它会解决它 - 我同意。 robertking:我明白你的意思,但是在正常的快速排序中,枢轴通常只移动两次(一次将其放在末尾/开始不碍事,然后一次将其放在分区末尾的中间),这只是在分区不退化时减少 O(n) 工作,不足以改变复杂性。如果您使用真正的中位数,我的建议是三向分区 - 那时不需要移动枢轴,最坏的情况应该是 O(n*log n)。
猜你喜欢
  • 2014-06-08
  • 2022-10-06
  • 2017-05-12
  • 2019-10-28
  • 2018-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-13
相关资源
最近更新 更多