在原位链表上实现自然合并排序,并且仅交换节点中的项

时间:2019-05-08 19:16:25

标签: java algorithm sorting linked-list mergesort

我必须在链接列表上实现自然的mergesort(这很简单),但是我不能更改节点的“ next”属性,而只能交换它们的值。我也不能倒退,因为节点没有“ prev”属性。 (链接列表没有随机访问权限)而且我无法创建新节点。

我只需要一些关于合并功能的提示。

我知道在合并两个子列表之前将它们排序是关键,但是我找不到解决方法。

这是Node类。他们保存通用项目和下一个节点的地址

private class Node {
    Item item;
    Node next;

    public String toString() {
        if (next == null) return "[" + item + "]" + "->" + "null";
        return "[" + item + "]" + "->" + next.item + ", ";
    }
}

2 个答案:

答案 0 :(得分:0)

为获得启发,请查看STL的inplace_sort实现。该算法的核心部分是巧妙的旋转。当然,它需要向后遍历,您可以通过递归来实现。

简而言之,合并部分沿着

    merge (begin, mid, end)
        left_mid = middle(begin, mid)
        right_mid = lower_bound(left_mid.value, mid, end)
        pivot = rotate(left_mid, mid, right_mid)
        merge(left, left_mid, pivot)
        merge(pivot, right_mid, end)
上面的

pivot是初始begin落入的节点。为简洁起见,省略了递归中的保全。

答案 1 :(得分:0)

这需要某种类型的就位排序,在这种情况下,它不再是自然的合并排序,最好是某种类型的混合。除非代码计划通过|来实现交换。 A = A xor B | B = A xor B | A = A或B |,该代码将需要一个临时节点来实现交换。如果不使用临时节点,则旋转会成为问题。

如果需要稳定性,则可以进行块合并排序,但是需要扫描列表以查找要用作工作区的唯一值,这是一种相当复杂的算法,并且对该算法进行了最新改进,例如圣杯。

https://en.wikipedia.org/wiki/Block_sort

https://github.com/Mrrl/GrailSort

如果不需要稳定性,则可以使用较为简单的递归算法

How to sort in-place using the merge sort algorithm?

尚不清楚自然合并排序如何适合这种情况。通常,自然合并排序是使用自然游程长度的自下而上合并。高效的位置合并排序算法需要根据运行大小将列表的一部分用作工作区域,这需要在扫描列表时使用计数器来确定运行大小或为工作区域设置边界。