[英]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.