【问题标题】:Re-ordering a Linked List in Python在 Python 中重新排序链表
【发布时间】:2011-07-29 20:17:45
【问题描述】:

我意识到这种数据结构最好使用内置列表类型来完成,但出于学术原因,我试图更多地理解这一点。鉴于我有一个这样的链表:

a -> b -> c -> d -> e -> f

我想将引用更改为

b -> a -> d -> c -> f -> e

换句话说,每一对都会被交换。我正在使用这两个类来创建一个链表。

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

class LinkedList:
    def __init__(self):
        self.cur_node = None

    def add_node(self, cargo):
        new_node = Node() 
        new_node.cargo = cargo
        new_node.next = self.cur_node 
        self.cur_node = new_node

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

    def reorder(self):
        # missing code here!


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.reorder()
ll.print_list()

有什么想法吗?

【问题讨论】:

  • 如果列表中有奇数个元素会发生什么?您是否尝试过实际编写 reorder 方法?
  • 如果你的节点数是奇数,你想在开头还是结尾的唯一节点?
  • 感谢您的回复。是的,奇数长度是允许的,唯一的节点应该保留在末尾。
  • 马特:是的,很多努力。我仍然很沮丧......

标签: python data-structures linked-list


【解决方案1】:

有时最好的办法是首先考虑“最佳解决方案的速度有多快?”这似乎很明显 O(length),所以在列表中运行的东西,最好是一次,将尽可能好。

鉴于此,您可能会发现最简单的选择是最好的。在伪代码中,它会是

 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.

正如 Matt 和 Jodaka 所说,如果允许使用奇数长度的列表,您确实需要决定如何处理奇数长度的列表。

【讨论】:

  • 感谢您的回复!是否可以更改引用而不是创建一个全新的对象?
  • 当然。 Consdier 实现了一个方法 swap(a,b),其中 a 和 b 是已链接列表中的节点。如果你把它做成一个双向链表,like 会更容易,所以你有一个指向 prev 和 next 的链接;一旦你弄清楚如何做到这一点,你就可以将其改进为仅在下一个使用。
【解决方案2】:

让我感到难过的是,“带有空头的双链表”数据结构并没有流行起来。在这个结构中,每个节点都指向它的前一个和下一个元素,列表本身以一个空节点开始,它只是一个标题,实际上从来没有任何数据。在初始空列表中,空头节点的 next 和 prev 指针指向节点本身。通过这个简单的初始化,其余的链接和取消链接代码几乎可以用几乎没有任何“如果 next 不是 None”或“如果 prev 不是 None”的东西来实现 - next 和 prev 指针是 never没有任何!看看 add_before、add_after 和 remove 的简单性,然后看看重新排序是多么容易。像双端队列一样,在列表的开头或结尾插入 O(1) - 只需调用 self.header.add_after 插入头部,或调用 self.header.add_before 插入末尾。

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()

【讨论】:

    猜你喜欢
    • 2018-12-06
    • 2015-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-28
    • 2013-10-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多