C++ 排序k排序链表?

C++ 排序k排序链表?,c++,algorithm,linked-list,time-complexity,big-o,C++,Algorithm,Linked List,Time Complexity,Big O,我在这里阅读解决方案: 关于如何将k个已排序的链表合并为一个链表 一个简单的解决方案是编写一个函数,用于处理两个链表,在前两个链表上调用它,然后使用上一个结果再次调用它,第三个链表,然后使用上一个结果和第四个链表再次调用它,依此类推 另一个更有效的解决方案是执行以下操作: 配对k列出并合并每一对 在第一次配对后,k列表被合并到平均长度为2N/k的k/2列表中,然后是k/4,k/8,依此类推 重复此过程,直到得到最终排序的链表 我的问题是:为什么第二个更有效,我的大脑拒绝接受这个事实,因为我认为我

我在这里阅读解决方案: 关于如何将k个已排序的链表合并为一个链表

一个简单的解决方案是编写一个函数,用于处理两个链表,在前两个链表上调用它,然后使用上一个结果再次调用它,第三个链表,然后使用上一个结果和第四个链表再次调用它,依此类推

另一个更有效的解决方案是执行以下操作:

配对
k
列出并合并每一对

在第一次配对后,
k
列表被合并到平均长度为
2N/k
k/2
列表中,然后是
k/4
k/8
,依此类推

重复此过程,直到得到最终排序的链表

我的问题是:为什么第二个更有效,我的大脑拒绝接受这个事实,因为我认为我们以不同的顺序做相同的工作。这种改进来自哪里?我们使用了哪些事实来加快速度


我在上次评论中澄清了我的问题。

让链表的长度为
[a,b,c,d]
。通过贪婪地合并前两个列表,我们得到:

  • 选择
    a
    b
    ,我们得到长度
    [a+b,c,d]
    总步数=(a+b)
  • 选择
    a+b
    c
    ,我们得到
    [a+b+c,d]
    总步数=(a+b)+(a+b+c)=2*a+2*b+c
  • 最后,我们得到
    [a+b+c+d]
    总步数=(2*a+2*b+c)+(a+b+c+d)=3*a+3*b+2*c+d

  • 正如您从
    total_steps
    中注意到的,前两个列表(开始合并)的系数最高。如果任一列表的长度相对较大,则性能将不是最佳的(因为系数较大,如图所示)。更好的方法是在每一步以最小长度合并列表(或问题中列出的k-方式合并)。

    假设第i个链表的长度为
    l[i]
    ,所有链表的总长度为
    l
    。另外,我假设您(读者)知道两个有序列表的双向合并具有
    O(a+b)
    时间复杂性,其中
    a
    是第一个列表的长度,
    b
    是第二个列表的长度

    第二种解决方案(解决方案2)具有稳定的时间复杂度,无论输入数据如何排列。在我们得到答案之前,任何链表的内容都被合并了
    logk
    次,因此在所有情况下,总的时间复杂度都是
    O(llogk)

    现在让我们考虑第一个解决方案(解决方案1)。考虑所有<代码> L[i] 相等(所有链表长度相同)的情况,总时间成本<代码> t>代码>为

    T = l[1] * k + l[2] * (k-1) + ... + l[k] * 1
      = l[1] * k(k+1) / 2
      = L * (k+1)/2
    
    这意味着解决方案1的最坏情况时间复杂度是
    O(Lk)
    ,这显然较慢

    解决方案1的一个直接改进是根据列表的长度合并列表,但实际上没有帮助。根据列表的长度对列表进行排序不是免费的,在上述情况下,这显然没有帮助,因此最坏情况下的时间复杂性没有得到改善


    解决方案2在最坏的情况下更好,在大多数情况下也更好。虽然您可以构建一个案例,说明解决方案1更快,但这并不意味着解决方案1总体上更好。

    好吧,假设我们有4个大小分别为100、5、4和3的链表。第一个策略将前两个合并为105个比较的上限,然后将其与4合并为105+(105+4)=214,然后将其与3合并为214+(214+3)=429个比较作为上限。两两合并将合并100和5,然后合并4和3以获得100+5+4+3=112,然后合并105+12以获得117。112+117=219个比较作为上限,小于429。@您愿意将其作为答案添加吗?它可以充实一点,但它已经基本上回答了这个问题。@谢谢,我从数学的角度理解这一点。但是,我是说为什么会这样?为什么两人一组通常比从左到右组好。我的大脑拒绝了这一部分……凭直觉,你可以想象,在每次合并中,较小的列表以较大的列表长度为代价被“消耗”,然后它变成一个较大的组合列表,长度之和作为新的长度。因此,您希望以最低成本使用所有列表。因此,应该通过消耗最小成本的较小列表(即短列表)来实现。如果你熟悉它,它类似于5个人用30秒灯过桥的逻辑拼图。