我被要求反转a以头为参数,其中head是链表,例如:1 - > 2 - >从已经定义的函数返回的3我尝试以这种方式实现函数reverse_linked_list:
def reverse_linked_list(head):
temp = head
head = None
temp1 = temp.next
temp2 = temp1.next
temp1.next = None
temp2.next = temp1
temp1.next = temp
return temp2
pass
class Node(object):
def __init__(self,value=None):
self.value = value
self.next = None
def to_linked_list(plist):
head = None
prev = None
for element in plist:
node = Node(element)
if not head:
head = node
else:
prev.next = node
prev = node
return head
def from_linked_list(head):
result = []
counter = 0
while head and counter < 100: # tests don't use more than 100 nodes, so bail if you loop 100 times.
result.append(head.value)
head = head.next
counter += 1
return result
def check_reversal(input):
head = to_linked_list(input)
result = reverse_linked_list(head)
assert list(reversed(input)) == from_linked_list(result)
以这种方式调用它:check_reversal([1,2,3])
。我为反转列表而编写的函数是[3,2,1,2,1,2,1,2,1]
,仅适用于长度为3的列表。如何对长度为n
的列表进行推广?
答案 0 :(得分:40)
接受的答案对我没有任何意义,因为它指的是一堆似乎不存在的东西(number
,node
,len
数字而不是函数)。由于这项作业可能已经很久了,我会发布我认为最有效的代码。
这是用于进行破坏性反转,您可以在其中修改现有列表节点:
def reverse_list(head):
new_head = None
while head:
head.next, head, new_head = new_head, head.next, head # look Ma, no temp vars!
return new_head
该函数的一个不那么花哨的实现将使用一个临时变量和几个赋值语句,这可能更容易理解:
def reverse_list(head):
new_head = None # this is where we build the reversed list (reusing the existing nodes)
while head:
temp = head # temp is a reference to a node we're moving from one list to the other
head = temp.next # the first two assignments pop the node off the front of the list
temp.next = new_head # the next two make it the new head of the reversed list
new_head = temp
return new_head
另一种设计是在不改变旧列表的情况下创建一个全新的列表。如果要将列表节点视为不可变对象,这将更合适:
class Node(object):
def __init__(self, value, next=None): # if we're considering Nodes to be immutable
self.value = value # we need to set all their attributes up
self.next = next # front, since we can't change them later
def reverse_list_nondestructive(head):
new_head = None
while head:
new_head = Node(head.value, new_head)
head = head.next
return new_head
答案 1 :(得分:21)
我发现blckknght的答案很有用,而且肯定是正确的,但我很难理解实际发生了什么,主要是因为Python的语法允许在一行上交换两个变量。我还发现变量名有点令人困惑。
在此示例中,我使用previous, current, tmp
。
def reverse(head):
current = head
previous = None
while current:
tmp = current.next
current.next = previous # None, first time round.
previous = current # Used in the next iteration.
current = tmp # Move to next node.
head = previous
将带有3个节点的单链表(head = n1
,tail = n3
)作为示例。
n1 -> n2 -> n3
在首次进入while
循环之前,previous
初始化为None
,因为在头部之前没有节点(n1
)。
我发现想象变量previous, current, tmp
&#39;移动&#39;链表,总是按顺序排列。
第一次迭代
previous = None
[n1] -> [n2] -> [n3]
current tmp
current.next = previous
第二次迭代
[n1] -> [n2] -> [n3]
previous current tmp
current.next = previous
第三次迭代
# next is None
[n1] -> [n2] -> [n3]
previous current
current.next = previous
由于while
循环在current == None
时退出,所以列表的新头必须设置为previous
,这是我们访问过的最后一个节点。
<强>被修改强>
在Python中添加完整的工作示例(带有注释和有用的str
表示)。我使用tmp
而不是next
,因为next
是关键字。然而,我碰巧认为这是一个更好的名称,使算法更清晰。
class Node:
def __init__(self, value):
self.value = value
self.next = None
def __str__(self):
return str(self.value)
def set_next(self, value):
self.next = Node(value)
return self.next
class LinkedList:
def __init__(self, head=None):
self.head = head
def __str__(self):
values = []
current = self.head
while current:
values.append(str(current))
current = current.next
return ' -> '.join(values)
def reverse(self):
previous = None
current = self.head
while current.next:
# Remember `next`, we'll need it later.
tmp = current.next
# Reverse the direction of two items.
current.next = previous
# Move along the list.
previous = current
current = tmp
# The loop exited ahead of the last item because it has no
# `next` node. Fix that here.
current.next = previous
# Don't forget to update the `LinkedList`.
self.head = current
if __name__ == "__main__":
head = Node('a')
head.set_next('b').set_next('c').set_next('d').set_next('e')
ll = LinkedList(head)
print(ll)
ll.revevse()
print(ll)
结果
a -> b -> c -> d -> e
e -> d -> c -> b -> a
答案 2 :(得分:4)
这是一种方法来反转列表&#39;到位&#39;。它以恒定时间O(n)运行,并使用零额外空间。
def reverse(head):
if not head:
return head
h = head
q = None
p = h.next
while (p):
h.next = q
q = h
h = p
p = h.next
h.next = q
return h
这是一个显示算法运行的动画 (为了动画的目的,#符号为Null / None)
答案 3 :(得分:1)
来自交互式python.org的节点类部分:http://interactivepython.org/runestone/static/pythonds/BasicDS/ImplementinganUnorderedListLinkedLists.html
我创建了反转功能。 反向循环中的所有注释都意味着第一次循环。然后它继续。
false
答案 4 :(得分:0)
我尝试了一种不同的方法,实现了LList的逆转。 给出列表1,2,3,4
如果您连续交换附近的节点,您将获得解决方案。
len=3 (size-1)
2,1,3,4
2,3,1,4
2,3,4,1
len=2 (size-2)
3,2,4,1
3,4,2,1
len=1 (size-3)
4,3,2,1
下面的代码就是这样。外部for循环连续减少列表的len以进行交换。 while循环交换节点的数据元素。
def Reverse(head):
temp = head
llSize = 0
while temp is not None:
llSize += 1
temp = temp.next
for i in xrange(llSize-1,0,-1):
xcount = 0
temp = head
while (xcount != i):
temp.data, temp.next.data = temp.next.data, temp.data
temp = temp.next
xcount += 1
return head
这可能不如其他解决方案有效,但有助于以不同的方式看待问题。希望您觉得这个有帮助。
答案 5 :(得分:0)
这是一张纸上的全部内容。包含链接列表的创建,以及反转它的代码。
包含一个示例,这样您就可以复制并粘贴到空闲的.py文件中并运行它。
class Node(object):
def __init__(self, value, next=None):
self.value = value
self.next = next
def reverse(head):
temp = head
llSize = 0
while temp is not None:
llSize += 1
temp = temp.next
for i in xrange(llSize-1,0,-1):
xcount = 0
temp = head
while (xcount != i):
temp.value, temp.next.value = temp.next.value, temp.value
temp = temp.next
xcount += 1
return head
def printnodes(n):
b = True
while b == True:
try:
print n.value
n = n.next
except:
b = False
n0 = Node(1,Node(2,Node(3,Node(4,Node(5,)))))
print 'Nodes in order...'
printnodes(n0)
print '---'
print 'Nodes reversed...'
n1 = reverse(n0)
printnodes(n1)
答案 6 :(得分:0)
def reverseLinkedList(head):
current = head
previous = None
nextNode = None
while current:
nextNode = current.nextNode
current.nextNode = previous
previous = current
current = nextNode
return previous
答案 7 :(得分:0)
大多数以前的答案是正确的,但是没有一个完整的代码,包括反向之前和之后的 insert方法,因此您实际上可以看到输出并进行比较。这就是为什么我要回答这个问题。当然,代码的主要部分是reverse_list()方法。 顺便说一下,这是在Python 3.7中。
class Node(object):
def __incurrent__(self, data=None, next=None):
self.data = data
self.next = next
class LinkedList(object):
def __incurrent__(self, head=None):
self.head = head
def insert(self, data):
tmp = self.head
self.head = Node(data)
self.head.next = tmp
def reverse_list(self):
current = self.head
prev = None
while current :
#create tmp to point to next
tmp = current.next
# set the next to point to previous
current.next = prev
# set the previous to point to current
prev = current
#set the current to point to tmp
current = tmp
self.head = prev
def print(self):
current = self.head
while current != None:
print(current.data,end="-")
current = current.next
print(" ")
lk = LinkedList()
lk.insert("a")
lk.insert("b")
lk.insert("c")
lk.print()
lk.reverse_list()
lk.print()
输出:
c-b-a-
a-b-c-
答案 8 :(得分:0)
以下是用于反转单链列表的通用代码,其中head作为函数的参数给出:
def reverseSll(ll_head):
# if head of the linked list is empty then nothing to reverse
if not ll_head:
return False
# if only one node, reverse of one node list is the same node
if not ll_head.next:
return ll_head
else:
second = ll_head.next # get the second node of the list
ll_head.next = None # detach head node from the rest of the list
reversedLL = reverseSll(second) # reverse rest of the list
second.next = ll_head # attach head node to last of the reversed list
return reversedLL
让我解释一下我在做什么:
1)如果head为null或head.next为null(列表中仅剩一个节点),则返回node
2)其他部分:取出第一个节点,删除其到列表其余部分的链接,反向列表的其余部分(reverseSll(second)),最后再次添加第一个节点,然后返回列表
Github link for the same
答案 9 :(得分:0)
您可以执行以下操作来反向链接单链列表(我假设您的列表彼此单联)。
首先,创建一个类Node,并启动一个默认构造函数,该构造函数将获取其中的数据值。
class Node:
def __init__(self, data):
self.data = data
self.next = None
此解决方案将“迭代”反向链接列表。 我正在创建一个名为SinglyLinkedList的类,它将具有一个构造函数:
class SinglyLinkedList:
def __init__(self):
self.head = None
然后,我编写了一种方法来反转列表,打印列表的长度,并打印列表本身:
# method to REVERSE THE LINKED LIST
def reverse_list_iterative(self):
prev = None
current = self.head
following = current.next
while (current):
current.next = prev
prev = current
current = following
if following:
following = following.next
self.head = prev
# Method to return the length of the list
def listLength(self):
count = 0
temp = self.head
while (temp != None):
temp = temp.next
count += 1
return count
# Method to print the list
def printList(self):
if self.head == None:
print("The list is empty")
else:
current_node = self.head
while current_node:
print(current_node.data, end = " -> ")
current_node = current_node.next
if current_node == None:
print("End")`
此后,我对列表及其内容进行了硬编码,然后将它们链接起来
if __name__ == '__main__':
sll = SinglyLinkedList()
sll.head = Node(1)
second = Node(2)
third = Node(3)
fourth = Node(4)
fifth = Node(5)
# Now linking the SLL
sll.head.next = second
second.next = third
third.next = fourth
fourth.next = fifth
print("Length of the Singly Linked List is: ", sll.listLength())
print()
print("Linked List before reversal")
sll.printList()
print()
print()
sll.reverse_list_iterative()
print("Linked List after reversal")
sll.printList()
输出将是:
单链接列表的长度为:5
1 -> 2 -> 3 -> 4 -> 5 -> End
反转之前的链接列表
反向链接列表
5 -> 4 -> 3 -> 2 -> 1 -> End
答案 10 :(得分:-6)
你可以使用mod函数来获取每次迭代的余数,显然它有助于逆转列表。我想你是Mission R和D的学生
head=None
prev=None
for i in range(len):
node=Node(number%10)
if not head:
head=node
else:
prev.next=node
prev=node
number=number/10
return head