我目前正在尝试了解排序算法,并且一直在研究伪代码并将其转换为python(使用python 3.6,IDE是Spyder 3.1.2)。我写了一个简单的冒泡排序:
def BubbleSort(array_to_sort):
n = len(array_to_sort) - 1
swapped = True
while (swapped):
swapped = False
for i in range(n):
if array_to_sort[i] > array_to_sort[i+1]:
array_to_sort[i+1], array_to_sort[i] = array_to_sort[i], array_to_sort[i+1]
swapped = True
return array_to_sort
和一个简单的选择排序:
def SelectionSort(array_to_sort):
n = len(array_to_sort)
for i in range(n):
minPos = i
for j in range(i+1, n):
if array_to_sort[j] < array_to_sort[minPos]:
minPos=j
if minPos != i:
array_to_sort[i], array_to_sort[minPos] = array_to_sort[minPos], array_to_sort[i]
return array_to_sort
并且正在尝试像这样计时他们:
def main():
array = RandomNumberArray()
a = timeit.Timer(functools.partial(BubbleSort, array))
print(a.timeit(1000))
b = timeit.Timer(functools.partial(SelectionSort, array))
print(b.timeit(1000))
RandomNumberArray只是生成我要排序的数字列表:
def RandomNumberArray():
return random.sample(range(0, 1000), 1000)
因为它们都具有相同的时间复杂度O(n 2 ),所以我期望它们花费的时间大致相同,但是我发现我的选择排序的性能相对较差到我的气泡排序中,例如在1000次迭代中具有1000个数字的数组-
BS结果:0.390 s
SS结果:63.618 s
以及经过10000次迭代的1000个数字的数组-
BS结果:2.074 s
SS结果:645.944 s
这些算法的实现是否存在问题,或者预计会有如此大的差异?我知道还有其他更快的排序方式,实际上没有人会真正使用BS或SS,但是我只是想了解为什么SS似乎比BS慢得多?
答案 0 :(得分:6)
这是不公平的比较,因为array
由第一个调用排序,然后传递到第二个调用。对于几种排序算法来说,已经排序的输入是最坏的情况。
气泡排序还具有O(n)个最佳情况时间复杂度,而选择具有O(n ^ 2)个最佳情况时间。
答案 1 :(得分:1)
@richard用户指出了主要问题。
总的来说,我希望每次编写的泡沫排序都能胜过选择排序。您的冒泡排序不是特别写得好,因为它没有利用算法在外循环每次迭代后提供的部分排序。也就是说,您有:
def BubbleSort(array_to_sort):
n = len(array_to_sort) - 1
swapped = True
while (swapped):
swapped = False
for i in range(n):
if array_to_sort[i] > array_to_sort[i+1]:
array_to_sort[i+1], array_to_sort[i] = array_to_sort[i], array_to_sort[i+1]
swapped = True
return array_to_sort
每次通过外循环,又有一个项目按顺序被推到数组的末尾。即,第一次通过循环,将最大项推到最后一个位置。下次,第二大的被推到倒数第二个位置,依此类推。但是您的代码没有利用这一点。而是连续比较已排序的项目。您可以使用以下方法大大改善代码:
def BubbleSort(array_to_sort):
n = len(array_to_sort) - 1
swapped = True
j = 0
while (swapped):
swapped = False
for i in range(0, n-j):
if array_to_sort[i] > array_to_sort[i+1]:
array_to_sort[i+1], array_to_sort[i] = array_to_sort[i], array_to_sort[i+1]
swapped = True
++j;
return array_to_sort
气泡排序通常比选择排序快,这有两个原因:1)如果没有进行交换,则有一个“提前退出”功能可以让您退出。 2)参照地点要好得多;您总是在比较和交换相邻项目。
答案 2 :(得分:0)
冒泡排序的一种更有价值的优化方法是,利用迭代进行的最后一次交换使数组的末端(在该点之外)处于最终状态。例如,在第一遍中:
a = [2, 1, 3, 4, 5, 6, 7, 8, 9, 10]
只有a[0]
和a[1]
被交换,这意味着不需要做更多的事情。第一遍已经确定a[0] < a[1] <= a[2] <= ... <= a[9]
。
这比swapped
标志更难编码,但是更有效。请注意,此代码不会不返回列表。您可能已经注意到,使对象(例如list.sort()
)发生突变的Python对象方法通常返回None
。这是故意的,以提醒您已对对象进行了突变。否则,就像您发布的原始测试代码中一样,很容易错误地假设该函数将原始对象留在了原处。
def bubbly(a):
n = len(a)
while n:
lastswap = 0
for i in range(1, n):
if a[i-1] > a[i]:
a[i-1], a[i] = a[i], a[i-1]
lastswap = i
n = lastswap