简体   繁体   English

如何使用另一个空链表递归地反转单链表?

[英]how to reverse a singly linked list recursively using another empty linked list?

Node and Linked List classes:节点和链表类:

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)

no matter what I do I just can't get it to work I've tried adding another reverse(h,q) in the Node class.无论我做什么,我都无法让它工作我尝试在节点 class 中添加另一个反向(h,q)。 I've been trying this for at least 5 hours now and any help will be much appreciated, This is actually for my assignment, I have the answer for the exact same question from last year, which is我已经尝试了至少 5 个小时,任何帮助将不胜感激,这实际上是我的任务,我有去年完全相同问题的答案,即

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

EDIT1:Sorry for the poor question asking technique. EDIT1:抱歉,提问技巧很差。 This is my first time asking question here.这是我第一次在这里提问。 I am trying to use this function to reverse a linked list h using another empty linked list qeg my linked list is: 1->2->3.我正在尝试使用此 function 使用另一个空链表 qeg 反转链表 h,我的链表是:1->2->3。 if I input:"ll.reverse(LnLs())",then I expect my linked will be changed to 3->2->1.如果我输入:“ll.reverse(LnLs())”,那么我希望我的链接将更改为 3->2->1。 at first I run this code it says "AttributeError: 'LnLs' object has no attribute 'nxt'".起初我运行这段代码时显示“AttributeError: 'LnLs' object has no attribute 'nxt'”。 Then I change the code to:然后我将代码更改为:

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

now it says NameError: name 'reverse' is not defined.现在它说 NameError: name 'reverse' is not defined。 if I add this function in the form of another kind of indentation(Sorry, I don't know what this is called in Python, I will use a picture as an example):如果我以另一种缩进的形式添加这个 function (对不起,我不知道这在 Python 中叫什么,我会以图片为例):

在此处输入图像描述

Then I run the testing codes and now my linked only has one element:然后我运行测试代码,现在我的链接只有一个元素:

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)

output: peach orange apple peach output:桃橙苹果桃

This is the point where I get confused as I don't know what else can I do.这是我感到困惑的地方,因为我不知道我还能做什么。 Thanks again.再次感谢。

Here are some of the issues:以下是一些问题:

  • In your first code block you defined reverse twice in the class, and by consequence the second definition overwrites the first.在您的第一个代码块中,您在 class 中定义了两次reverse ,因此第二个定义覆盖了第一个。

  • The second reverse method makes a call to reverse .第二个reverse方法调用reverse There is no global reverse function, only a method with that name.没有全局reverse function,只有同名的方法。

  • If you change the "signature" of reverse to take an extra linked list argument, you need to also change the call to reverse that the constructor makes, because that call is currently not passing a second argument.如果您更改reverse的“签名”以采用额外的链表参数,您还需要更改构造函数对reverse的调用,因为该调用当前未传递第二个参数。 Or, alternatively, you should think of another name for this second reverse method.或者,您应该为第二种reverse方法考虑另一个名称。

  • Even if you correct the reverse recursive call to be called like a method, you don't have a linked list to call it on.即使您将reverse递归调用更正为像方法一样被调用,您也没有链接列表来调用它。 t is a node, not a linked list, so if you would write t.reverse(h) , it would lead to an error, as a Node instance does not have a reverse method. t是一个节点,而不是一个链表,所以如果你写t.reverse(h) ,它会导致错误,因为 Node 实例没有reverse方法。 In fact, at the moment you want to make the reverse recursive call, you don't have the two linked lists that are required to make the call.事实上,在您想要进行reverse递归调用的那一刻,您并没有进行调用所需的两个链表。

So, I would suggest to call the new method differently, copy_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)

Explanation解释

The idea of this function is to pop each element from the first list and push it to the second.这个 function 的想法是从第一个列表中弹出每个元素并将其推送到第二个。 At the end the first list will be empty, and the second list will have the reversed list.最后第一个列表将为空,第二个列表将具有反向列表。

Note that this is destructive to the first list, so it might be nice to have this happen to a copy of the list.请注意,这对第一个列表具有破坏性,因此最好将这种情况发生在列表的副本上。 That way the caller will not be unpleasantly surprised with an emptied list.这样,调用者就不会对清空列表感到不愉快。

So we first check whether the second argument as given (it defaults to None ).所以我们首先检查第二个参数是否给定(默认为None )。 If not, then we make a copy of the current linked list (using iter , which calls the __iter__ method), and call the function again, but this time on the copy, and providing the second argument.如果没有,那么我们制作当前链表的副本(使用iter ,它调用__iter__方法),并再次调用 function,但这次是在副本上,并提供第二个参数。

Then we extract the first element from the list and push it (at the front of) the second list.然后我们从列表中提取第一个元素并将其推送(在第二个列表的前面)。 This is repeated via recursive calls until the first list is empty.这通过递归调用重复,直到第一个列表为空。 The result is returned.结果被返回。

This also means that the caller needs to capture the return value of the call to copy_reverse .这也意味着调用者需要捕获对copy_reverse的调用的返回值。 So your main code would look as follows:因此,您的主要代码如下所示:

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)

Or, shorter:或者,更短:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM