繁体   English   中英

计算比较次数并使用编程和/或数学方法分析特定算法的效率

[英]Counting number of comparisons and analyzing the efficiency of a particular algorithm using programming and/or mathematics

def three_way_merge(L1,L2,L3):
    L = []
    i1 = 0
    i2 = 0
    i3 = 0
    done1 = False
    done2 = False
    done3 = False
    while not (done1 and done2 and done3):
        if not done1 and (done2 or L1[i1] < L2[i2]) and (done3 or L1[i1] < L3[i3]):
            L.append(L1[i1])
            i1 += 1
            done1 = i1 >= len(L1)
        elif not done2 and (done3 or L2[i2] < L3[i3]):
            L.append(L2[i2])
            i2 += 1
            done2 = i2 >= len(L2)
        else:
            L.append(L3[i3])
            i3 += 1
            done3 = i3 >= len(L3)
    return L

我想对所发现的算法进行最坏的比较,因为我的算法课即将进行考试,并且希望能够进行这种分析。 我的想法是写一个程序,创建此“最坏情况”的许多随机示例(我猜是这样的类型: L1 = [9,10,11], L2 = [6,7,8], L3 = [3,4,5] ,其中所有列表都已排序,但是L3L2值严格小于L1等),然后每次进行任何比较时,我都会增加一个计数器并返回最终计数,然后尝试找出输出中的某种模式,但这似乎是实现这一目标的低效方法。

有没有一种方法可以像对合并排序中的经典合并进行分析一样来计算?

通常,生成随机输入并不是确定最坏情况下运行时间的好方法。 例如,快速排序平均以O(n log n)运行,但在最坏的情况下,它以O(n ^ 2)运行。 但是,即使生成了大量随机样本,对于中等大小的n,您也永远不会接近最坏的情况。 相反,请尝试手动构造最坏情况的输入。

在这种情况下,似乎最坏的情况是假设每个数组的长度为N,

L1 = (N,2N,2N+1,...,3N-3,3N)
L2 = (N+1,N+2,...,2N-1,3N-1)
L3 = (1,2,...,N-1,3N-2)

要了解原因,请跟踪算法的执行。 发生的第一件事是L3的前N-1个元素将添加到L 循环的这些迭代中的每一个都会有3个比较:两个在第一个if语句中,第二个在比较中。 请注意,我们需要L1[1]<L2[1]否则, if第一个比较,则将跳过第二个比较

接下来是元素L[1]=N ,该元素仅进行一个比较。

之后是L[2]的前N-1个元素,每个元素都需要两个比较,一个与L1比较,一个与L3

接下来是L1的下N-2个元素,每个元素都有一个比较。

此时,每个列表中只剩下一个元素。 首先选择L3 ,进行3个比较,然后对L2进行一个比较,仅此而已。

总数是

(N-1)*(3+2+1)+3+1 = 6N - 2

我认为这是最坏的情况,但您也许可以从某个地方再挤出一个。 另外,我可能犯了一个错误,在这种情况下,这里的某人可能会抓住它。 接下来应该做的就是尝试证明这是最坏的运行时间。

PS此算法不是合并三个列表的最佳方法。 从三个列表的最前面选择最小的元素最多只需要进行2个比较,而不是3个。如果您发现L2<L1L1<L3则不必比较L2L3因为您已经知道L2较小。

编辑时:不难证明这实际上是最坏的情况。 假设所有列表都不为空,则每次迭代的比较次数为:

  • 如果L3最小且L1 <L2则为3
  • 如果L2最小则为2
  • 如果L1最小则为1

由于每个列表只能是最小的N次,因此该位置的上限为N * 6。 因此,完成证明只需要检查列表变为空的末尾会发生什么。

正如您所说,最糟糕的情况是让L3(或L2)的所有数字都小于L1,因为IF子句将失败,并且它将执行elif节以计算更多的比较。

在第一个IF中(假设我们将每次检查布尔值(例如done1,done2等)都视为一个单独的比较),并考虑到通常以惰性方式计算逻辑表达式,那么最糟糕的情况是在其他变量之前达到done1 = true(可以保证L1的值大于L2和L3),done2都没有达到true(可以保证L2中的值大于L3中的值),因此L1 [i1] <L2 [i2]在每个步骤中进行计算。

当L3完成并且每个周期进入IF部分时,由于done3为true,因此仅执行4个比较,并且由于延迟,因此不计算最后一个比较。 当进入省略号部分时,同样适用于两个比较。

当L2完成时,IF子句中仅进行3个比较(因为done2和done3为真)

因此,具有此配置(L1 >> L2 >> L3),此算法将执行:

Len(L3)*(3(while子句)+ 5(IF子句)+ 3(elif节)+1(done3计算))+ Len(L2)*(3(while子句)+ 4( IF子句)+ 2(elif节)+1(done2计算))Len(L1)*(3(while子句)+ 3(IF子句)+ 1(done1计算))

所以最后的数是

镜头(L3)* 12 +镜头(L2)* 10 +镜头(L1)* 7

在对这3个数组进行排序的任何情况下,计算顺序都是相同的,顺序为Len(3)+ Len(2)+ Len(1)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM