【问题标题】:Linked Lists: How to remove odd numbers?链表:如何删除奇数?
【发布时间】:2019-12-04 04:09:30
【问题描述】:

我目前正在学习在线计算机科学入门课程,并且刚刚了解了链表的概念。虽然我了解链表的概念,但我仍然不确定如何处理链表。

因此,我寻求帮助以解决以下问题,这将有助于我理解链表:

编写一个给定链表的函数(不在 LinkedList 类定义中),将更改该链表以过滤掉奇数。函数返回后,链表将只有偶数。

我不确定如何访问列表中的节点并检查它们是奇数还是偶数并相应地删除或保留它们。

如果这似乎是一个微不足道的问题,我深表歉意,但如果有任何可能帮助我学习的帮助,我将不胜感激。

链表和节点类的代码(由在线课程提供):

class Node:
    def __init__(self, data=None, next_node=None):
        self.data = data
        self.next = next_node

    def __str__(self):
        return str(self.data)


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

    def print_list(self):
        node = self.head
        while node is not None:
            print(node, end=' ')
            node = node.next
        print('')

    def add_at_head(self, node):
        node.next = self.head
        self.head = node
        self.length += 1

    def remove_node_after(self, node):
        if node.next is not None:
            temp = node.next
            node.next = node.next.next
            temp.next = None
            self.length -= 1

    def remove_first_node(self):
        if self.head is None:
            return
        temp = self.head
        self.head = self.head.next
        temp.next = None
        self.length -= 1

    def print_backward(self):
        def print_nodes_backward(node):
            if node.next is not None:
                print_nodes_backward(node.next)
            if node is not None:
                print(node, end=' ')

        if self.head is not None:
            print_nodes_backward(self.head)

        print('')

【问题讨论】:

  • 在不知道您如何表示您的链接列表的情况下,实际上不可能回答这个问题。您应该发布一些代码,显示您遇到问题的地方。
  • @MarkMeyer 问题是我不确定如何继续制作所需的功能。我知道我需要检查元素是奇数还是偶数并消除可能性。我知道如何处理列表,但不知道链表。
  • 这个想法是从头到尾迭代列表同时记住前一个节点;当你找到一个垃圾节点时,将remove_node_after 应用到记住的节点,或者如果我们还没有时间记住任何东西,则将头部移动到当前节点。
  • @Amadan 这正是我想要做的,我的问题是我不确定如何遍历链表。通常对于列表/数组,我使用 while/for 循环,但这不适用于链表。如果我只能弄清楚如何做到这一点,我相信我可以解决它。
  • 我希望online courses 不会建议不正确记录您的代码,至少提供docstrings

标签: python algorithm function linked-list


【解决方案1】:

假设您有一个简单的链表,如下所示:

class LinkedList:
    class ListNode:
        def __init__(self, data):
            self.data = data
            self.next = None
    def __init__(self):
        self.head = None
    def add(self, data):
        if self.head is None:
            self.head = LinkedList.ListNode(data)
        else:
            current_node = self.head
            while current_node.next is not None:
                current_node = current_node.next
            current_node.next = LinkedList.ListNode(data)
    def __str__(self):
        ret = "["
        current_node = self.head
        while current_node is not None:
            ret = ret + str(current_node.data)
            if current_node.next is not None:
                ret = ret + ", "
            current_node = current_node.next
        ret = ret + "]"
        return ret

换句话说,LinkedList 包含一个head,即ListNode。链接列表中的每个元素都包含在ListNode 中,每个ListNode 指向列表中的下一个元素。

如您所见,为了向列表中添加元素,如果列表为空(即self.head is None),我们要么在头部创建一个节点,要么通过不断跳转到列表的末尾遍历每个ListNode.next 元素,从head 开始。我们还使用此范例来打印列表的字符串表示形式。

因此,要从链表中删除任何节点,我们可以简单地更改引用它的节点,以便跳过我们要删除的节点。到那时它就会消失。

要删除所有包含奇数数据的列表节点,我们可以这样做:

    def remove_odds(self):
        # special case: head node
        # remove odd head elements by simply setting head to the next element after
        while (self.head is not None) and (self.head.data % 2 == 1):
            self.head = self.head.next
        # regular case: the rest of the nodes
        current_node = self.head
        while (current_node is not None) and (current_node.next is not None):
            # if the next node's data is odd, then
            if current_node.next.data % 2 == 1:
                # skip that node by pointing this node's .next to the next node's .next
                current_node.next = current_node.next.next
            # otherwise, move forwards in the list
            else:
                current_node = current_node.next

概念证明:

>>> lst = LinkedList()
>>> lst.add(2)
>>> lst.add(5)
>>> lst.add(6)
>>> lst.add(3)
>>> lst.add(7)
>>> lst.add(8)
>>> lst.add(10)
>>> lst.add(1)
>>> lst.add(4)
>>> print(lst)
[2, 5, 6, 3, 7, 8, 10, 1, 4]
>>> lst.remove_odds()
>>> print(lst)
[2, 6, 8, 10, 4]

【讨论】:

  • 谢谢你,这是我首先做的,但是在线课程练习正在寻找一个不在LinkedList类中的函数(我不确定这是否是正确的表达方式)。
  • 我会将有关如何调整此信息的信息留给您作为练习。算法是最重要的——可以肯定的是,您尝试与之交互的链表结构应该已经定义了具有.data.next 字段的节点。查看您获得的文档和项目描述,并尝试找出它们是什么,然后调整此解决方案以使用它。
  • 谢谢。我相信我已经弄明白了。
【解决方案2】:

从评论中复制:想法是从头到尾迭代列表同时记住前一个节点;当你找到一个垃圾节点时,将remove_node_after 应用于记住的节点,或者如果我们还没有时间记住任何东西,则将头部移动到当前节点。

代码将是这样的(未经测试):

class LinkedList:
    # ...
    def delete_if(self, pred):
        prev = None
        curr = self.head
        while curr:
            if pred(curr.data):
                if prev:
                    self.remove_node_after(prev)
                else:
                    self.head = curr
            prev = curr
            curr = curr.next

llist.delete_if(lambda x: x % 2 == 1) # delete if odd

【讨论】:

  • 谢谢你,这是我首先做的,但是在线课程练习正在寻找一个不在LinkedList类中的函数(我不确定这是否是正确的表达方式)。
  • 它不一定是方法(类中的函数)。即使没有放在名为 delete_if(llist, lambda x: x % 2 == 1) 的类中,相同的函数也可以工作(尽管您可能想将 self 重命名为其他名称,例如 llist,因此不会让人感到困惑)。
  • 我相信我已经弄明白了。谢谢!
【解决方案3】:
# Mahmoud AL-Mokdad
# this course on Udemy By SEfactoru right?
# use my code ?
def filter_even(ll):
    first_node = ll.head
    while (first_node is not None) and (first_node.data % 2 != 0):
        ll.remove_first_node()
        first_node = ll.head
    node = first_node
    while node is not None and node.next is not None:
        if node.next.data % 2 != 0:
            ll.remove_node_after(node)
        else:
            node = node.next

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-10
    • 1970-01-01
    • 2020-05-14
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-05
    相关资源
    最近更新 更多