【问题标题】:how to reverse a singly linked list recursively using another empty linked list?如何使用另一个空链表递归地反转单链表?
【发布时间】:2021-03-14 06:05:02
【问题描述】:

节点和链表类:

class Node:
    def __init__(self, elm, nxt):
        self.elm = elm
        self.nxt = nxt
    
class LnLs:
    def __init__(self, s = None):
        self.head = None
        if s:
            for x in s:
                self.push(x)
            self.reverse()
            
    def __bool__(self):
        return self.head is not None

    def top(self):
        if not self:
            raise IndexError
        return self.head.elm

    def push(self, x):
        self.head = Node(x, self.head)

    def pop(self):
        x = self.top()
        self.head = self.head.nxt 
        return x

    def __iter__(self):
        p = self.head
        while p:
            yield p.elm
            p = p.nxt

    def index_of(self, x):
        for i, y in enumerate(self):
            if x == y:
                return i
        return -1

    def __getitem__(self, i):
        for j, x in enumerate(self):
            if i == j:
                return x
        raise IndexError

    def reverse(self):
        q, p = None, self.head
        # q points to the previous node
        while p:
            t = p.nxt
            p.nxt = q
            q = p
            p = t
        self.head = q
        
    def reverse(h, q):
        if h.head is None:
            return q
        else:
            t = h.head.nxt
            h.head.nxt = q
            return reverse(t, h)

无论我做什么,我都无法让它工作我尝试在 Node 类中添加另一个 reverse(h,q)。 我已经尝试了至少 5 个小时,任何帮助将不胜感激! 这实际上是我的任务,我有去年完全相同的问题的答案,即

def reverse(h, q):
    if h is None:
        return q
    else:
        t = h.nxt
        h.nxt = q
    return reverse(t, h)

EDIT1:对于糟糕的提问技巧感到抱歉。这是我第一次在这里提问。我正在尝试使用此函数使用另一个空链表 q 反转链表 h。例如我的链表是:1->2->3。如果我输入:“ll.reverse(LnLs())”,那么我希望我的链接将更改为 3->2->1。起初我运行这段代码,它说“AttributeError:'LnLs'对象没有属性'nxt'”。然后我把代码改成:

def reverse(h, q):
        if h.head is None:
            return q
        else:
            t = h.head.nxt
            h.head.nxt = q
            return reverse(t, h)

现在它显示 NameError: name 'reverse' is not defined。如果我以另一种缩进的形式添加这个函数(对不起,我不知道这在Python中叫什么,我以一张图片为例):

然后我运行测试代码,现在我的链接只有一个元素:

if __name__ == '__main__':
    ll = LnLs()
    ll.push('apple')
    ll.push('orange')
    ll.push('peach')
    for x in ll:
        print(x)
    ll.reverse(LnLs())
    for x in ll:
        print(x)

输出: 桃子 橙 苹果 桃子

这是我感到困惑的地方,因为我不知道我还能做什么。再次感谢。

【问题讨论】:

  • 请提供预期的MRE - Minimal, Reproducible Example。显示中间结果与预期结果的偏差。我们应该能够将您的代码块粘贴到文件中,运行它并重现您的问题。这也让我们可以在您的上下文中测试任何建议。您发布的代码没有做任何事情:您有两个类和一个函数,但这些都没有被调用过。
  • 我们还希望您在错误点之前跟踪可疑值。您对他们如何获得这些价值观感到困惑? “不能让它工作”不是问题规范。

标签: python linked-list singly-linked-list


【解决方案1】:

这里有一些问题:

  • 在您的第一个代码块中,您在类中定义了两次reverse,结果第二个定义覆盖了第一个。

  • 第二个reverse 方法调用reverse。没有全局 reverse 函数,只有一个具有该名称的方法。

  • 如果您更改reverse 的“签名”以获取额外的链表参数,您还需要更改构造函数对reverse 的调用,因为该调用当前未传递第二个参数。或者,您应该为第二个reverse 方法考虑另一个名称。

  • 即使您将reverse 递归调用更正为像方法一样被调用,您也没有链接列表来调用它。 t 是一个节点,而不是一个链表,所以如果你写 t.reverse(h) 会导致错误,因为 Node 实例没有 reverse 方法。事实上,在您想要进行reverse 递归调用的那一刻,您并没有进行调用所需的两个链表。

所以,我建议以不同的方式调用新方法,copy_reverse

    def copy_reverse(self, other=None):
        if other is None:   # in case the argument was not provided
            # ...make a copy of the list so the original will not be destroyed,
            # ...and pass an empty linked list as argument 
            return LnLs(iter(self)).copy_reverse(LnLs())
        if not self:
            return other
        other.push(self.pop())
        return self.copy_reverse(other)

说明

这个函数的想法是从第一个列表中弹出每个元素并将其推送到第二个列表中。最后,第一个列表为空,第二个列表为反向列表。

请注意,这对第一个列表具有破坏性,因此最好将这种情况发生在列表的 副本 上。这样一来,调用者就不会对空列表感到不愉快。

所以我们首先检查第二个参数是否给定(默认为None)。如果没有,那么我们复制当前链表(使用iter,它调用__iter__ 方法),并再次调用该函数,但这次是在副本上,并提供第二个参数。

然后我们从列表中提取第一个元素并将其推送到第二个列表的前面。这通过递归调用重复,直到第一个列表为空。结果返回。

这也意味着调用者需要捕获对copy_reverse的调用的返回值。所以你的主要代码如下所示:

ll = LnLs()
ll.push('apple')
ll.push('orange')
ll.push('peach')
for x in ll:
    print(x)
result = ll.copy_reverse()  # <-- changed
for x in ll:
    print(x)

或者,更短:

ll = LnLs(['apple', 'orange', 'peach'])
print(list(ll))
result = ll.copy_reverse()
print(list(result))

【讨论】:

    猜你喜欢
    • 2012-11-05
    • 2020-10-02
    • 1970-01-01
    • 2018-11-16
    • 2020-12-04
    • 2020-07-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多