Re-ordering a Linked List in Python

拈花ヽ惹草 提交于 2019-12-02 12:39:38

Sometimes the best thing is to first think "how fast would an optimal solution be?" This seems pretty apparently O(length), so something that runs through the list, preferably once, is going to be about as good as you can do.

Given that, you're probably going to find the simplest choice is best. In pseudocode, it would be

 get the first element in left
 get the second element in right
 append them to a new list as right->left
 repeat until you run out of list.

As Matt and Jodaka note, you do need to decide what to do with an odd-length list, if an odd-length list is permitted at all.

It saddens me that the "doubly-linked-list-with-null-header" data structure has not caught on more. In this structure, each node points to its previous and next elements, and the list itself starts with a null Node, which is a header only, and never actually has any data. In the initial empty list, the null header node's next and prev pointers point back to the node itself. With this simple initialization, the rest of the linking and unlinking code can be implemented with hardly any "if next is not None" or "if prev is not None" stuff - the next and prev pointers are never None! Look at the simplicity of add_before, add_after, and remove, and then see how easily reorder is done. Like a deque, insertion at the beginning or end of the list is O(1) - just call self.header.add_after to insert at the head, or self.header.add_before to insert at the end.

class Node:
    def __init__(self):
        self.cargo = None 
        self.next = self
        self.prev = self

    def add_after(self, other):
        other.next = self.next
        other.prev = self
        self.next.prev = other
        self.next = other

    def add_before(self, other):
        other.next = self
        other.prev = self.prev
        other.prev.next = other
        self.prev = other


class LinkedList:
    def __init__(self):
        self.header = Node()

    def __bool__(self):
        return self.header.next != self.header
    __nonzero__ = __bool__  # for older Pythons

    def empty(self):
        return not self

    def add_node(self, cargo):
        new_node = Node() 
        new_node.cargo = cargo
        self.header.add_before(new_node)

    @staticmethod
    def pop(node):
        node.prev.next = node.next
        node.next.prev = node.prev
        node.next = node.prev = node
        return node

    def print_list(self):
        node = self.header.next
        while node != self.header:
            print node.cargo
            node = node.next

    def reorder(self):
        node = self.header.next
        while node != self.header and node.next != self.header:
            node.add_before(self.pop(node.next))
            node = node.next


ll = LinkedList()
ll.add_node("a")
ll.add_node("b")
ll.add_node("c")
ll.add_node("d")
ll.add_node("e")
ll.add_node("f")
ll.print_list()
ll.reorder()
ll.print_list()
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!