Python 二进制插入排序与快速排序
我在研究不同的排序算法及其性能(),然后我尝试自己实现一些排序算法。我还想改进它们,因此,在编写插入排序的代码时,我想为什么不使用二进制搜索,因为数组的第一部分已经排序,为了摆脱交换,可以使用额外的数组。代码可在以下位置找到: 然后我像往常一样实现了快速排序(): 因此,它基本上运行给定的Python 二进制插入排序与快速排序,python,arrays,algorithm,performance,sorting,Python,Arrays,Algorithm,Performance,Sorting,我在研究不同的排序算法及其性能(),然后我尝试自己实现一些排序算法。我还想改进它们,因此,在编写插入排序的代码时,我想为什么不使用二进制搜索,因为数组的第一部分已经排序,为了摆脱交换,可以使用额外的数组。代码可在以下位置找到: 然后我像往常一样实现了快速排序(): 因此,它基本上运行给定的sort函数,并打印排序数组所需的时间。所以我至少运行了10次这段代码,每次二进制插入排序几乎快了9倍(9s>1s)。但我认为快速排序是最快的。。。如果我比较这两种排序算法,我会说二进制插入排序更好,尽管它需要
sort
函数,并打印排序数组所需的时间。所以我至少运行了10次这段代码,每次二进制插入排序几乎快了9倍(9s>1s)。但我认为快速排序是最快的。。。如果我比较这两种排序算法,我会说二进制插入排序更好,尽管它需要O(n)额外的空间(最糟糕的时间复杂度是O(n*log(n)),这比快速排序更好。
这是个错误吗?快速排序实际上比二进制插入排序更糟糕吗?我试图在互联网上找到它,但找不到真正与我的代码相似的东西。也许它甚至不是二进制插入排序,而是其他东西…(另一个名称)?让我们看看您编写插入排序的尝试:
def insertion_sort_optimized(arr):
array = [arr[0]]
for i in range(1, len(arr)):
index = bisect_left(array, i)
array.insert(index, i)
return array
您没有插入数组值,而是插入索引。以递增的顺序。这是错误的,正确的版本需要O(n^2)而不是O(n logn)(由于每个
插入的线性时间)。这是我的二进制插入排序
时间复杂度为(N^2)/4+Nlog2(N/(2e))
def二进制索引(arr:Union[Iterable,List,Tuple,np.ndarray],value,reverse:bool=False):
如果值arr[-1]:
返回长度(arr)
开始,结束=0,长度(arr)
尽管如此:
如果结束-开始值:
回程起动
其他:
返回开始+1
其他:
如果arr[start]<值:
回程起动
其他:
返回开始+1
mid=(开始+结束)//2
如果反向为假:
如果值arr[mid]:
结束=中间
其他:
开始=中间
def BinaryInsertionSortOptimized(数组:联合[Iterable,List,Tuple,np.ndarray],反向:bool=False):
如果反向为假:
对于范围(1,len(数组))中的索引:
如果数组[索引-1]<数组[索引]:
持续
i=二进制索引(arr=array[0:index],value=array[index],reverse=reverse)
关键点=数组[索引]
数组[i+1:索引+1]=数组[i:索引]
数组[i]=关键点
其他:
对于范围(1,len(数组))中的索引:
如果数组[index-1]>数组[index]:
持续
i=二进制索引(arr=array[0:index],value=array[index],reverse=reverse)
关键点=数组[索引]
数组[i+1:索引+1]=数组[i:索引]
数组[i]=关键点
返回数组
您的快速排序没有得到有效实施,您已经将其变成了二次排序:快速排序(小部分)+[pivot]+快速排序(大部分)
此外,在快速排序中,选择pivot是至关重要的,您使用的是最幼稚的策略。最后请注意,快速排序并不是应用最广泛的。例如,Python使用高度调优的自适应mergesort,Timsort。那么Java现在是否默认(采用Timsort)。@HeapOverflow你是什么意思?我不明白你的意思。。。我如何改进它?您的快速排序看起来像是在重新生成内容,而它被设想为就地排序。也许制作所有这些副本都要花费时间。但是快速排序不应该仍然是最快的吗?与Timsort和AdaptiveMergeSort相比?但是你的评论让我怀疑你对BigOoh不太了解。。。非常感谢。我看错地方了
def quicksort(arr):
if len(arr) <= 1:
return arr
smaller_part = []
larger_part = []
pivot = arr[len(arr) - 1]
for i in range(len(arr) - 1):
if arr[i] < pivot:
smaller_part.append(arr[i])
else:
larger_part.append(arr[i])
return quicksort(smaller_part) + [pivot] + quicksort(larger_part)
def test_sorting_algorithm(sort=None, version="normal", returns=False, n=1000000):
if version.lower() == "normal":
print("Normal version:")
else:
print("Optimized version:")
arr = [int(random() * n) for _ in range(n)]
print(arr)
start = time.time()
if returns:
arr = sort(arr)
else:
sort(arr)
end = time.time()
print(arr)
print(f"Time elapsed: {end - start}\n")
def insertion_sort_optimized(arr):
array = [arr[0]]
for i in range(1, len(arr)):
index = bisect_left(array, i)
array.insert(index, i)
return array
def BinaryIndexing(arr: Union[Iterable, List, Tuple, np.ndarray], value, reverse: bool = False):
if value < arr[0]:
return 0
elif value > arr[-1]:
return len(arr)
start, end = 0, len(arr)
while True:
if end - start <= 1:
if reverse is False:
if arr[start] > value:
return start
else:
return start + 1
else:
if arr[start] < value:
return start
else:
return start + 1
mid = (start + end) // 2
if reverse is False:
if value < arr[mid]:
end = mid
else:
start = mid
else:
if value > arr[mid]:
end = mid
else:
start = mid
def BinaryInsertionSortOptimized(array: Union[Iterable, List, Tuple, np.ndarray], reverse: bool = False):
if reverse is False:
for index in range(1, len(array)):
if array[index - 1] < array[index]:
continue
i = BinaryIndexing(arr=array[0:index], value=array[index], reverse=reverse)
key_point = array[index]
array[i + 1:index + 1] = array[i:index]
array[i] = key_point
else:
for index in range(1, len(array)):
if array[index - 1] > array[index]:
continue
i = BinaryIndexing(arr=array[0:index], value=array[index], reverse=reverse)
key_point = array[index]
array[i + 1:index + 1] = array[i:index]
array[i] = key_point
return array