Quicksort - 三个媒体选择的枢轴

时间:2017-03-21 14:17:33

标签: python quicksort

def quicksort(L, low, high):
    total = 0
    if low < high:
        pivot_location, total = Partition(L, low, high)
        total += quicksort(L,low,pivot_location)
        total += quicksort(L,pivot_location + 1, high)
    return total 

def Partition(L, low, high):
    print(L)
    #print(high)
    total = 0
    if (high - low) % 2 == 0:
        middle = (high - low) // 2 - 1
    else:
        middle = ((high - low) // 2) + low
    print(L[low])
    print(L[high - 1])
    print(L[middle])
    numbers = []
    numbers.append(L[low])
    numbers.append(L[middle])
    numbers.append(L[high - 1])
    if L[low] > L[middle] and L[low] < L[high - 1]:
        pivot = L[low]
    elif L[low] >L[high -1] and L[low] < L[middle]:
        pivot = L[low]
    elif L[middle] < L[low] and L[middle] > L[high -1]:
        temp = L[low]
        L[low] = L[middle]
        L[middle] = temp
        pivot = L[low]
    elif L[middle] < L[high - 1] and L[middle] > L[low]:
        temp = L[low]
        L[low] = L[middle]
        L[middle] = temp
        pivot = L[low]
    elif L[high - 1] < L[low] and L[high - 1] > L[middle]:
        temp = L[low]
        L[low] = L[high - 1]
        L[high - 1] = temp
        pivot = L[low]
    else:
        temp = L[low]
        L[low] = L[high - 1]
        L[high - 1] = temp
        pivot = L[low]
    print(pivot)
    i = low + 1
    for j in range(low + 1,high,1):
        total += 1
        if L[j] < pivot:
            temp = L[j]
            L[j] = L[i]
            L[i] = temp
            i += 1
    temp = L[low]
    L[low] = L[i -1]
    L[i - 1] = temp
    #print(L)
    return i - 1,total  

c = [2148,9058,7742,3153,6324,609,7628,5469,7017,504]
print(quicksort(c, 0, len(c)))  
print(c)

我已经用这种方式实现了快速排序。我尝试使用第一个元素作为枢轴,最后一个元素作为枢轴,它完美地工作。但是,我无法弄清楚如何选择三个元素的中位数:第一,中,最后。任何关于如何在每个递归调用中选择中间元素的帮助。请注意,我想将每个递归调用作为参数传递给整个数组,因为我不想使用任何额外的内存。

2 个答案:

答案 0 :(得分:1)

将3个元素的中位数放到位的另一种方法:

def compareswap(L,a,b):
    L[a], L[b] = min(L[a],L[b]),max(L[a],L[b])

def medianfirst(L,a,b,c):
    compareswap(L,b,a) # L[b]<=L[a]
    compareswap(L,b,c) # L[b]<=L[c] i.e L[b] smallest
    compareswap(L,a,c) # L[a]<=L[c] i.e L[c] largest 

现在使用medianfirst中的Partition

    medianfirst(L,low,middle,high-1)
    pivot = L[low]

而不是大if-elif-else块。

----更新----

(固定middle在偶数元素间隔中首先选择) 为方便起见,修改后的Partition

def Partition(L, low, high):
    print(L)
    total = 0
    middle = (low+high-1)//2
    medianfirst(L,low,middle,high-1)
    pivot = L[low]
    i = low + 1
    for j in range(low + 1,high,1):
        total += 1
        if L[j] < pivot:
            L[i],L[j] = L[j],L[i]
            i += 1
    L[low],L[i-1] = L[i-1],L[low]
    return i - 1,total

答案 1 :(得分:0)

def partition_median(L, low, high):
    left = L[low]
    right = L[high-1]
    length = high - low
    if length % 2 == 0:
        middle = L[int(low + length/2 - 1)]
    else:
        middle = L[int(low + length/2)]
    pivot = median(left, right, middle)
    pivotindex = L.index(pivot) #works only for unique values
    L[pivotindex] = L[low]
    L[low] = pivot
    i = low + 1
    for j in range(low + 1, high):
        if L[j] < pivot:
            temp = L[j]
            L[j] = L[i]
            L[i] = temp
            i += 1
    leftend = L[low]
    L[low] = L[i-1]
    L[i-1] = leftend
    return i - 1

好吧,多亏了我得到的帮助,还有一些想法我设法用上面的分区子程序实现我想要的东西!