简体   繁体   English

链表:如何删除奇数?

[英]Linked Lists: How to remove odd numbers?

I am currently taking an online computer science introductory course and have just learned the concept of a linked list.我目前正在学习在线计算机科学入门课程,并且刚刚学习了链表的概念。 Though I understand the concept of linked lists, I still am unsure as how to deal with linked lists.虽然我了解链表的概念,但我仍然不确定如何处理链表。

As such, I seek out help in solving the following problem, which will be of significant help for my understanding of linked lists:因此,我寻求帮助解决以下问题,这对我理解链表有很大帮助:

Write a function (not in LinkedList class definition) that given a linked list, will change that linked list to filter out odd numbers.编写一个函数(不在 LinkedList 类定义中),给定一个链表,将更改该链表以过滤掉奇数。 Immediately after the function returns, the linked list will only have even numbers.函数返回后,链表将只有偶数。

I am unsure as to how to access the nodes in the list and check whether they are odd or even and remove or keep them accordingly.我不确定如何访问列表中的节点并检查它们是奇数还是偶数并相应地删除或保留它们。

I apologize if this seems like a trivial question, but I would appreciate any help that might help me learn.如果这似乎是一个微不足道的问题,我深表歉意,但我将不胜感激任何可能帮助我学习的帮助。

The code for the linked list and node classes (as provided by the online course):链表和节点类的代码(由在线课程提供):

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('')

Let's say you have a bare-bones simple linked list that looks like this:假设您有一个简单的简单链表,如下所示:

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

In other words, the LinkedList contains a single head , which is a ListNode .换句话说, LinkedList包含一个head ,它是一个ListNode Every element in the Linked List is contained in a ListNode , and each ListNode points towards the next element in the list.链表中的每个元素都包含在一个ListNode ,每个ListNode指向列表中的下一个元素。

As you can see, for adding an element to the list, we either create a node at the head if the list is empty (ie self.head is None ), or we traverse to the end of the list by continuously jumping to the .next element for each ListNode , starting from the head .如您所见,为了向列表中添加元素,如果列表为空(即self.head is None ),我们要么在头部创建一个节点,要么通过不断跳转到.next每个ListNode .next元素,从head开始。 We also use this paradigm for printing a string representation of our list.我们也使用这个范例来打印我们列表的字符串表示。

So, to remove any node from the linked list, we can simply change the node that references it, so that the node we want to remove gets skipped.因此,要从链表中删除任何节点,我们可以简单地更改引用它的节点,以便我们要删除的节点被跳过。 At which point it will disappear.在这一点上它会消失。

To remove all list nodes containing odd-numbered data, we might do something like this:要删除所有包含奇数数据的列表节点,我们可能会这样做:

    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

Proof of concept:概念证明:

>>> 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]

Copied from comment: The idea is to iterate through the list head-to-tail while remembering the previous node ;复制自评论:想法是在记住前一个节点的同时从头到尾遍历列表; when you find a garbage node, apply remove_node_after to the remembered node, or move the head to the current node if we haven't had time to remember anything yet.当你发现一个垃圾节点时,将remove_node_after应用到记住的节点,或者如果我们还没有时间记住任何东西,则将头部移动到当前节点。

The code would be something like this (untested):代码将是这样的(未经测试):

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
# 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

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

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