当前位置: 首页 > 知识库问答 >
问题:

在python中反转链表

宗政子辰
2023-03-14

我被要求反转一个以head为参数的参数,其中as head是一个链表,例如:1-

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

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\u reversion([1,2,3])。我编写的用于反转列表的函数给出了[3,2,1,2,1,2,2,1],并且只适用于长度为3的列表。如何将其概括为长度n的列表?

共有3个答案

能正青
2023-03-14

下面是一种“就地”反转列表的方法。它以恒定时间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

这里有一个动画来显示算法正在运行。
(#为动画目的象征空/无)

柳胜
2023-03-14

我发现blckknght的答案很有用,而且肯定是正确的,但我很难理解到底发生了什么,这主要是因为Python的语法允许在一行上交换两个变量。我还发现变量名有点混乱。

在这个例子中,我使用以前的,当前的,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-

在第一次进入while循环之前,previous被初始化为None,因为头部之前没有节点(n1)。

我发现想象变量previous、current、tmp沿着链接列表“移动”是很有用的,总是按照这个顺序。

第一次迭代

previous=None

[n1]-

第二次迭代

[n1]-

第三次迭代

# next is None

[n1]-

因为循环退出时当前==无列表的新头部必须设置为前一个,这是我们访问的最后一个节点。

编辑

在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

苏季同
2023-03-14

被接受的答案对我来说毫无意义,因为它指的是一堆似乎不存在的东西(numbernodelen作为一个数字而不是一个函数)。因为这个作业可能已经很久了,我将发布我认为最有效的代码。

这用于执行破坏性反转,其中修改现有列表节点:

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
 类似资料:
  • 问题内容: 我被要求反转一个以head为参数的参数,其中head是一个链表,例如:1-> 2-> 3这是从已经定义的函数返回的,我试图以这种方式实现函数reverse_linked_list: 称为:。我编写的用于反转列表的函数具有给定的功能,并且仅适用于长度为3的列表。如何将其概括为长度为列表的? 问题答案: U可以使用mod函数获取每次迭代的余数,并且显然可以帮助反转列表。我想你是R和D团的学

  • NowCoder 解题思路 递归 // java public ListNode ReverseList(ListNode head) { if (head == null || head.next == null) return head; ListNode next = head.next; head.next = null; ListNode

  • 问题内容: Python的str对象没有内置的反向函数。实现这种方法的最佳方法是什么? 如果提供一个非常简洁的答案,请详细说明其效率。例如,str对象是否转换为其他对象等。 问题答案: 怎么样: 这是扩展切片语法。它的工作方式是通过保留和并指定步骤来反转字符串。

  • 问题内容: 必须是O(n)并且是就地(空间复杂度为1)。下面的代码可以工作,但是有没有更简单或更完善的方法? 问题答案: 编辑以删除每次迭代的额外比较:

  • 问题内容: 如何在Python中执行以下操作? 我需要一个数组的元素,但是要从头到尾。 问题答案: 你可以通过以下方式使用该函数: 请注意,它不会返回列表。你可以使用来获得反向列表。

  • 一、题目 定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。 二、解题思路 ①遍历。将指向下一个节点的指针指向上一个节点。 ②递归。先让指向下一个节点的指针为空,然后递归调用,最后再将指向下一个节点的指针指向上一个节点。 三、解题代码 遍历 /** * 反转单链表 * @param head * @return */ p