Algorithm 二进制插入排序与复杂性
我有一个关于在插入排序算法中使用二进制搜索的简单问题。更准确地说,在通常的插入排序的每个步骤中,我们不是将元素与之前(排序)子数组中的所有元素进行线性比较,而是在该排序子数组中使用二进制搜索来查找元素所属的位置 我知道这减少了算法进行比较的次数(O(logn)而不是O(n)),但每个步骤所需的交换次数仍然占主导地位,复杂性仍然是O(n^2) 我也知道复杂性与运行时间的关系并不那么容易。我尝试比较了两种算法的运行时间,其“小”值为n(数组大小),最高可达500000左右。二进制插入排序总是比通常的插入排序快 两者都是O(n^2)的事实告诉我,当n变得足够大时,运行时间应该是相似的,对吗?你知道在这种情况下,什么“足够大”才能真正看到类似的运行时间吗 两者都是O(n^2)的事实告诉我,当n变得足够大时,运行时间应该是相似的,对吗 小心——这不是真的<当Algorithm 二进制插入排序与复杂性,algorithm,sorting,Algorithm,Sorting,我有一个关于在插入排序算法中使用二进制搜索的简单问题。更准确地说,在通常的插入排序的每个步骤中,我们不是将元素与之前(排序)子数组中的所有元素进行线性比较,而是在该排序子数组中使用二进制搜索来查找元素所属的位置 我知道这减少了算法进行比较的次数(O(logn)而不是O(n)),但每个步骤所需的交换次数仍然占主导地位,复杂性仍然是O(n^2) 我也知道复杂性与运行时间的关系并不那么容易。我尝试比较了两种算法的运行时间,其“小”值为n(数组大小),最高可达500000左右。二进制插入排序总是比通常的
n
变大时,code>n^2和2n^2
永远不会靠得更近;他们的距离越来越远。但两者都是O(n^2)
那么,说你的两个算法都是O(n^2)
是什么意思呢?好的,这意味着最终每一个都可以在上面被n^2
的某个常数倍数所限定。对于二进制插入排序,它可能是10n^2
,而对于标准插入排序,它可能是1000n^2
。两者都是n^2
,尽管效率可能相差100
(在本例中)
复杂性告诉您的关于特定函数的行为的信息比它告诉您该函数如何与其他函数进行比较的信息要多。例如,如果您知道您的函数是
O(n^2)
,那么您就知道对于n
的大值,f(n+1)
的增长不会超过某个常数倍n+1
(为什么?因为n^2
的导数是2n
,是线性的,这说明连续项之间的差异是线性增长的)。理论上二进制插入排序复杂度是O(log_2(n!)),
这是在O(n²)和O(n log(n))之间,实际上离O(n log(n))更近。这是我的二进制插入排序:时间复杂度是(n^2)/4+Nlog2(n/(2e))。确实,如果执行交换,它的成本会比数组重写高得多。在这种情况下,时间复杂度是NK/4+Nlog2(n/(2*e)),介于O(n^2)和O之间(NlogN)
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]=关键点
返回数组
并不意味着当n变得足够大时,运行时间应该是相似的。它只是意味着当n接近无穷大时,两者将以大致相同的速率接近无穷大的运行时间。这是一个很好的解释,肯定有助于澄清我的误解。这两个答案都不应该是相似的,r是吗?,也不是在这种情况下,什么“足够大”才能真正看到类似的运行时间?
(如果(v1>v2)=reverse:
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