![]() |
1
3
你的算法通过递归使用O(N)堆栈空间
以下是修改后的版本:
使用合并排序对链表进行排序应仅使用 O(对数(N)) 空间和 O(N log(N)) 时间。 以下是一些改进此算法的想法:
这是一个使用列表长度和非递归的修改版本
请注意,您还可以简化
|
![]() |
2
1
一种选择是将节点合并排序,就像它们是单个列表节点一样,然后在完成时进行一次传递以设置前面的指针,并更新尾部指针。 另一种选择是使用类似于C++std::list和std::list::sort的东西。使用循环双链表。有一个虚拟节点将“next”用作“head”,将“prev”用作“tail”。合并排序和合并的参数是迭代器或指针,仅用于跟踪运行边界,因为节点是通过在原始列表中移动来合并的。merge函数使用std::list::splice将第二次运行中的节点合并到第一次运行中。逻辑是,如果第一个run元素小于或等于第二个run元素,只需将迭代器或指针前进到第一个run,否则从第二个runs中删除节点,并将其插入到第一个runs的当前节点之前。如果涉及删除+插入步骤,这将自动更新虚拟节点中的头指针和尾指针。 将结构节点更改为:
会更通用一些。 由于在创建列表时分配了虚拟节点,因此begin==dummy->;接下来,最后==虚拟->prev和end==虚拟。 |
![]() |
3
1
我不是提供有关算法的深入分析的最佳人选
海上舞台
符号。无论如何,用一个已经被接受的“经典”答案来回答一个问题是很好的,因为有可能在没有太大压力的情况下探索替代解决方案。
该策略首先想知道是否有可能在不颠倒代码的情况下跟踪候选尾部元素。主要候选函数是决定排序列表中节点顺序的函数:
现在,由于在比较之后我们决定哪个节点将在排序列表中排名第一,我们将得到一个
“失败者”
那会更靠近尾巴。因此,通过与每个步骤的当前尾部元素进行进一步比较,最终我们将能够更新
合并功能将具有额外的
除了“传播”之外,不需要对代码进行更多更改
测试
为了测试这个修改,我必须编写一个基本的
我做了几次测试;这里我只举一个例子,在这个例子中,我省略了问题和上述答案中的函数:
在这个特定的测试中,我得到了以下输出:
结论
|
![]() |
Nhmanas · c中的合并排序堆栈溢出++ 7 年前 |
![]() |
MitterHai · 合并排序堆栈溢出错误 7 年前 |
![]() |
Alpaca · 我的合并排序java代码有什么问题? 7 年前 |
![]() |
paper man · 合并排序大小不为2^n的数组 7 年前 |