【问题标题】:Trouble implementing a recursive Add method for a Linked-List class为 Linked-List 类实现递归 Add 方法时遇到问题
【发布时间】:2020-06-01 19:18:33
【问题描述】:

我需要为链表类递归实现add 方法。我无法让我的代码工作。这是我目前所拥有的:

class LinkedList:
    def __init__(self):
        self.head = None

    def add(self, val, current_node=0):

        if current_node == 0:
            current_node = self.head

        if current_node is None:
            current_node = Node(val)
        else:
            self.add(self, val, current_node.next)

这个实现我哪里出了问题?

【问题讨论】:

    标签: python python-3.x recursion linked-list


    【解决方案1】:

    这是对递归的滥用。如果链表的长度大于调用堆栈大小,则类无故中断。与迭代实现相比,它的编写效率和直观性也较低。

    话虽如此,教授通常会要求以递归方式实现自然不适合递归的算法。一起玩,我会写一个处理实际递归的内部助手。这避免了可能使调用者感到困惑的尴尬默认参数,并使他们能够破坏函数的合同。

    def add(self, val):
        def add_recursively(curr, prev):
            if curr:
                add_recursively(curr.next, curr)
            else:
                if prev:
                    prev.next = Node(val)
                else:
                    self.head = Node(val)
    
        add_recursively(self.head, None)
    

    最初尝试的主要问题是:

    if current_node is None:
        current_node = Node(val)
    

    没有对链中前一个节点的引用,current_node 实际上并没有使用上述操作附加到任何东西,所以它只是在函数返回时被垃圾收集。

    如果允许使用迭代,这是一种更自然的方法:

    def add(self, val):
        curr = self.head
        prev = None
    
        while curr:
            prev, curr = curr, curr.next
    
        if prev:
            prev.next = Node(val)
        else:
            self.head = Node(val)
    

    这是一个最小的完整用法示例:

    class Node:
        def __init__(self, val, next_node=None):
            self.val = val
            self.next = next_node
    
        def __str__(self): 
            return str(self.val)
    
    class LinkedList:
        def __init__(self):
            self.head = None
    
        def add(self, val):
            curr = self.head
            prev = None
    
            while curr:
                prev, curr = curr, curr.next
    
            if prev:
                prev.next = Node(val)
            else:
                self.head = Node(val)
    
        def __str__(self): 
            nodes = []
            curr = self.head
    
            while curr:
                nodes.append(curr.val)
                curr = curr.next
    
            return "[" + " -> ".join(nodes) + "]"
    
    if __name__ == "__main__":
        llist = LinkedList()
        llist.add("bananas")
        llist.add("apples")
        llist.add("cranberries")
        print(llist) # => [bananas -> apples -> cranberries]
    

    除此之外,考虑为您的 LinkedList 类保留一个 self.tail 节点引用。这将使添加操作 O(1) 而不是 O(n)。

    【讨论】:

    • 非常感谢您的全程解释。我尝试测试您的代码版本,它在大多数情况下都有效。但是,当我尝试在以前为空的链表中打印新添加的节点的数据时,它会打印节点对象 id 而不是值。例如,以下打印节点对象的 ID 而不是节点对象的值:linkedlist1 = LinkedList(), print(linkedlist1.head.data)
    • 您在此处提供的小代码 sn-p 不应该工作,因为 head 最初是 None 但我在测试代码中打印数据没有问题。我添加了一个用法示例——如果它不适合您,请告诉我。
    • 我的示例测试代码出错了,让您的代码正常工作。我还根据您提供的 add 方法创建了所有其他链表方法,非常感谢您为我指路!抱歉回复晚了!
    • 很高兴它成功了!如果您还没有,请查看what to do when someone answers my question
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-22
    • 2020-03-29
    • 2022-01-15
    • 2020-05-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多