Gnome排序比快速排序更快?

时间:2016-08-16 16:17:17

标签: algorithm python-3.x sorting quicksort mergesort

我决定深入研究排序算法,并在python中实现了一些如bubble,selection,gnome,insertion,merge和quick sort。然而,当我运行它们并比较时间时,gnome排序是O(n ^ 2)比fastsort更快,它有一个O(nlogn)我相信。 问题:有人可以向我解释为什么我的gnome排序算法比我的快速和合并排序算法更快,并且优化我的方法,以便它们比效率较低的算法排序更快。谢谢。 (P.S.如果您从未听说过gnome排序,这将是一个有用的链接Wikipedia Gnome Sort Algorithm

# Sorting lib
# author: Aniekan Umoren
# course: LEAP EngTech
# date started: 2016-08-09
# last modified: 2016-08-16

import time
from random import randrange

def bubble_sort(arr):
    k = 0
    n = len(arr)
    for numSweeps in range(n-1):
        for i in range(n-k-1):
            if arr[i] > arr[i+1]:
                temp = arr[i]
                arr[i] = arr[i+1]
                arr[i+1] = temp
        k += 1
    return arr

def selection_sort(arr):
    n = len(arr)
    k = 0
    for numSweeps in range(n-1):
        minimum = arr[k]
        for i in range(k,n):
            if arr[i] < minimum:
                temp = arr[k]
                arr[k] = arr[i]
                arr[i] = temp
                minimum = arr[k]
        k += 1
    return arr

def gnome_sort(arr):
    pos = 0
    while pos < len(arr):
        if pos == 0 or arr[pos] >= arr[pos-1]:
            pos += 1
        else:
            temp = arr[pos]
            arr[pos] = arr[pos-1]
            arr[pos-1] = temp
            pos -= 1
    return arr

def insertion_sort(arr):
    for i in range(len(arr)):
        x = arr[i]
        j = i -1
        while j >= 0 and arr[j] > x:
            arr[j+1] = arr[j]
            j -= 1
        arr[j+1] = x
    return arr

def merge(arr1,arr2):
    arr3 = []
    size1 = len(arr1); size2 = len(arr2)
    i1 = 0; i2 = 0
    while i1 < size1 or i2 < size2: #both list aren't empty
        if i1 == size1:
            arr3.append(arr2[i2])
            i2 += 1
        elif i2 == size2:
            arr3.append(arr1[i1])
            i1 += 1
        elif arr1[i1] <= arr2[i2]:
            arr3.append(arr1[i1])
            i1 += 1
        elif arr2[i2] < arr1[i1]:
            arr3.append(arr2[i2])
            i2 += 1
    return arr3

def merge_sort(Arr, start, end):
    if start < end:
        # size = (start + end + 1)
        mid = (start+end)//2
        arr1 = merge_sort(Arr,start, mid)
        arr2 = merge_sort(Arr, mid+1, end)
        Arr[start:end+1] = merge(arr1, arr2)
    return Arr[start:end+1]

def partition(Arr, start, end):
    rand = start + randrange(end-start)
    temp = Arr[start]
    Arr[start] = Arr[rand]
    Arr[rand] = temp
    i = start + 1
    for j in range(start+1, end+1):
        if Arr[j] < Arr[start]:
            temp = Arr[i]
            Arr[i] = Arr[j]
            Arr[j] = temp
            i += 1
    temp = Arr[start]
    Arr[start] = Arr[i-1]
    Arr[i-1] = temp
    return (Arr,i-1)

def quick_sort(Arr, start, end):
    if start < end:
        part_result = partition(Arr, start, end)
        Arr = part_result[0]
        piv_pos = part_result[1]
        quick_sort(Arr, start, piv_pos-1)
        quick_sort(Arr, piv_pos+1, end)
    if end == len(Arr)-1:
        return Arr


def main():
    start_time = time.time()
    li1 = [3, 1234, 123, 214, 21, 124, 125, 213,
           34, 354, 2345,62, 34, 623, 34, 34, 53465,
           346, 346434, 537373, 5347,73, 234, 62, 36,
           27, 247, 4742, 47472, 24, 742, 57, 24, 7245, 24]
    li2 = [3, 21, 24, 24, 27, 34, 34, 34, 34, 36,
           57, 62, 62, 73, 123, 124, 125, 213, 214,
           234, 247, 346, 354, 623, 724, 742, 1234,
           2345, 4742, 5347, 7245, 47472, 53465, 346434, 537373]
    li3 = sorted(li2, reverse = True)
    li4 = [3,5,26,42,2,6]

    for i in range(10000):
        result = bubble_sort(li1)
    print("BUBBLE SORT: %s seconds" % (time.time() - start_time))

    start_time = time.time()
    for i in range(10000):
        result = gnome_sort(li1)
    print("GNOME SORT: %s seconds" % (time.time() - start_time)) # why is gnome sort sooo fast if it has a O(n**2)

    start_time = time.time()
    for i in range(10000):
        result = selection_sort(li1)
    print("SELECTION SORT: %s seconds" % (time.time() - start_time))

    start_time = time.time()
    for i in range(10000):
        result = insertion_sort(li1)
    print("INSERTION SORT: %s seconds" % (time.time() - start_time))

    size = len(li1)
    start_time = time.time()
    for i in range(10000):
        result = merge_sort(li1, 0, size-1)
    print("MERGE SORT: %s seconds" % (time.time() - start_time))

    size = len(li1)
    start_time = time.time()
    for i in range(10000):
        result = quick_sort(li1, 0, size-1)
    print("QUICK SORT: %s seconds" % (time.time() - start_time))

    start_time = time.time()
    for i in range(10000):
        result = sorted(li1)
    print("TIM SORT: %s seconds" % (time.time() - start_time))

main()

1 个答案:

答案 0 :(得分:3)

您的排序会改变输入而不是返回新列表,因此在第一次排序后,输入将被排序并保持排序。 Gnome sort在已经排序的输入上是O(n)。