Re-ordering a Linked List in Python
I realize this sort of data structure is better done with built in list type, but I'm trying to understand this more for academic reasons. Given that I have a linked list like this:
a -> b -> c -> d -> e -> f
I would like to change the references to
b -> a -> d -> c -> f -> e
In other words every pair gets switched. I am using these two classes to create a linked list.
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
开发者_JAVA技巧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()
Any ideas?
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()
精彩评论