簡體   English   中英

非遞歸快速排序

[英]Non-recursive Quicksort

我如何使底部 function 非遞歸,我試過但通過創建新函數,這不是這個問題的重點。 第一個 function 是給定的,inplace_quicksort_non_recursive 是我創建的。

import random

def inplace_quick_sort(S, a, b):
  """Sort the list from S[a] to S[b] inclusive using the quick-sort algorithm."""
  if a >= b: return                                      # range is trivially sorted
  pivot = S[b]                                           # last element of range is pivot
  left = a                                               # will scan rightward
  right = b-1                                            # will scan leftward
  while left <= right:
    # scan until reaching value equal or larger than pivot (or right marker)
    while left <= right and S[left] < pivot:
      left += 1
    # scan until reaching value equal or smaller than pivot (or left marker)
    while left <= right and pivot < S[right]:
      right -= 1
    if left <= right:                                    # scans did not strictly cross
      S[left], S[right] = S[right], S[left]              # swap values
      left, right = left + 1, right - 1                  # shrink range

  # put pivot into its final place (currently marked by left index)
  S[left], S[b] = S[b], S[left]
  # make recursive calls
  inplace_quick_sort(S, a, left - 1)
  inplace_quick_sort(S, left + 1, b)
  return left
  

def inplace_quick_sort_nonrecursive(S):
    stack = []                # create a stack for storing sublist start and end index
    a = 0                             # get the starting and ending index of a given list
    b = len(S) - 1
    pivot = S[b]
 
    stack.append((a, b))              # push the start and end index of the array into the stack

    while len(stack) > 0:                      # loop till stack is empty
      a, b = stack.pop()              # remove top pair from the list and get sublist starting and ending indices
      pivot = inplace_quick_sort(S, a, b)           # rearrange elements across pivot
      if pivot - 1 > a:               # push sublist indices containing elements that are less than the current pivot to stack
        stack.append((a, pivot - 1))
      if pivot + 1 < b:               # push sublist indices containing elements that are more than the current pivot to stack
        stack.append((pivot + 1, b))


origList = random.sample(range(100), 100)
origList2 = random.sample(range(100), 100)
origList.extend(origList2)
inplace_quick_sort_nonrecursive(origList)

errorIndices = []
for i in range(100):
  ind1 = 2*i
  ind2 = ind1+1
  if origList[ind1] != i:
    errorIndices.append(ind1)
  if origList[ind2] != i:
    errorIndices.append(ind2)
if len(errorIndices) == 0:
  print("PASSED")
else:
  print("Error in indices: " + str(errorIndices))

我需要創建什么以使底部 function 變為非遞歸

在您的inplace_quick_sort_nonrecursive function 內部,您計算 pivot 的方式沒有任何意義。 當您根據樞軸的值將子數組 A[start, end] 划分為三個部分時(可以隨機或有意選擇,就像最初在這里您選擇最后一個元素作為樞軸一樣):
A[start, p − 1], A[p] 和 A[p + 1...end],其中 p 是 pivot 所在的位置。 pivot左右部分滿足以下條件:
• A[i] ≤ A[p], i ∈ [start, p − 1],
• A[i] > A[p], i ∈ [p + 1, end]

使用它進行分區:

def partition(array, lo, hi):
    pivot = array[hi]
    i = lo - 1
    for j in range(lo, hi):
        if array[j] < pivot:
            i += 1
            temp = array[i]
            array[i] = array[j]
            array[j] = temp
    temp = array[i + 1]
    array[i + 1] = array[hi]
    array[hi] = temp
    return i + 1

閱讀Lomuto 的 Partition方法以更好地理解代碼。

問題是使用 Hoare 分區方案的變體(但有問題)。 經典的 Hoare 分區方案示例。 注意 Hoare 將分區拆分為元素 <= pivot 和元素 >= pivot; pivot 和元素 == pivot 可以在任何地方結束,所以 Hoare 只將分區分成 2 部分(pivot 沒有到位,不能從后面的分區步驟中排除)。

import random
from time import time

def qsort(a):
    if len(a) < 2:                      # if nothing to sort, return
        return
    stack = []                          # initialize stack
    stack.append([0, len(a)-1])
    while len(stack) > 0:               # loop till stack empty
        lo, hi = stack.pop()            # pop lo, hi indexes
        p = a[(lo + hi) // 2]           # pivot, any a[] except a[hi]
        i = lo - 1                      # Hoare partition
        j = hi + 1
        while(1):
            while(1):                   #  while(a[++i] < p)
                i += 1
                if(a[i] >= p):
                    break
            while(1):                   #  while(a[--j] < p)
                j -= 1
                if(a[j] <= p):
                    break
            if(i >= j):                 #  if indexes met or crossed, break
                break
            a[i],a[j] = a[j],a[i]       #  else swap elements
        if(j > lo):                     # push indexes onto stack
            stack.append([lo, j])
        j += 1
        if(hi > j):
            stack.append([j, hi])

# test sort
a = [random.randint(0, 2147483647) for r in range(512*1024)]
s = time()
qsort(a)
e = time()
print e - s

# check to see if data was sorted
f = 0
for i in range (1 ,len(a)):
    if(a[i-1] > a[i]):
        f = 1
        break
if(f == 0):
    print("sorted")
else:
    print("error")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM