【问题标题】:How to navigate through a linked list without using a for or while loop?如何在不使用 for 或 while 循环的情况下浏览链接列表?
【发布时间】:2021-03-18 15:49:50
【问题描述】:

我试图在不使用 for 循环或 while 循环的情况下遍历链表。

class VaccList:
    class Appointment:
        def __init__(self, name, age, city, date):
            assert type(name) is str, 'name variable must be a string'
            assert type(age) is int, 'age variable must be a integer'
            assert type(city) is str, 'city variable must be a string'
            assert type(date) is datetime, 'date variable must be a datetime object'
            assert name != None, 'name variable cannot be empty'
            assert age >= 18 and age <= 100, 'age must be between 18 and 100'
            #   ADD 6 asserts.  4 for the types and name cannot be empty, 
            #   and age must be between 18 and 100

            self.name = name
            self.age = age
            self.city = city
            self.date = date
            self.confirmed = False
            self.next = None

        def __str__(self):
            s = "Appointment for " + self.name + " on " + str(self.date) + " age:" + str(self.age) + "  city:" + self.city
            if self.confirmed:
                s += " (confirmed)"
            else:
                s += " (unconfirmed)"
            return s

    def __init__(self):
        self.head = None
        self.tail = None


    def confirm(self, name):    
        '''
        Find an appointment for a person with the given name and set confirmed to true.
        Return a string message  "not found", "confirmed", "already confirmed."
    '''
        # Note... no loop!
        #  assert, type of name and non-empty string
        assert type(name) is str, 'name variable must be a string'
        assert name != None
        current = self.head
        if current.name == name:
            if current.confirmed == False:
                current.confirmed = True
                return 'confirmed'
            else:
                return 'already confirmed'

这是我创建的课程中的方法,我正在尝试确认约会,除非它们已经被确认。我可以确认第一次约会,但如果我正在搜索的姓名不是约会列表中的第一个名字,我将如何找到下一个要检查的名字?

【问题讨论】:

  • 你可以尝试使用递归
  • 为什么要尝试在没有循环的情况下执行此操作?你能使用另一种不需要线性搜索的数据结构吗?
  • @Samwise 只在没有循环的情况下这样做,因为它意味着学校项目。
  • 为了回答这个问题,我们至少需要看一下链表中节点的结构。请edit您的问题并添加此内容。
  • 问我如何得知 Python 缺乏 TCO(这是在现实世界中,哈哈)

标签: python recursion linked-list


【解决方案1】:

下面是如何按照@user15270287 早期建议的那样递归地执行操作来避免循环。我必须添加一个 add_appt() 方法才能将它们添加到列表中,以便能够创建一个用于测试代码,因此您的里程可能会有所不同。

除此之外和最后的单元测试,所有的变化都是confirm()方法。

from datetime import datetime


class VaccList:
    class Appointment:
        def __init__(self, name, age, city, date):
            assert type(name) is str, 'name variable must be a string'
            assert type(age) is int, 'age variable must be a integer'
            assert type(city) is str, 'city variable must be a string'
            assert type(date) is datetime, 'date variable must be a datetime object'
            assert name != None, 'name variable cannot be empty'
            assert age >= 18 and age <= 100, 'age must be between 18 and 100'
            #   ADD 6 asserts.  4 for the types and name cannot be empty,
            #   and age must be between 18 and 100

            self.name = name
            self.age = age
            self.city = city
            self.date = date
            self.confirmed = False
            self.next = None

        def __str__(self):
            s = ("Appointment for " + self.name + " on " + str(self.date) + " age:"
                    + str(self.age) + "  city:" + self.city)
            if self.confirmed:
                s += " (confirmed)"
            else:
                s += " (unconfirmed)"
            return s

    def __init__(self):
        self.head = None
        self.tail = None

    # ADDED FOR TESTING PURPOSES.
    def add_appt(self, name, age, city, date):
        date = datetime.strptime(date, '%Y-%m-%d')
        new_appt = VaccList.Appointment(name, age, city, date)
        new_appt.next = self.head
        self.head = new_appt

    def confirm(self, name, start=None):
        '''
        Find an appointment for a person with the given name and set confirmed to true.
        Return a string message  "not found", "confirmed", "already confirmed."
        '''
        # Note... no loop!
        #  assert, type of name and non-empty string
        assert type(name) is str, 'name variable must be a string'
        assert name != None

        # Start at beginning of list unless different node is specified.
        current = self.head if start is None else start
        if current is None:
            return 'list is empty!'
        if current.name == name:
            if current.confirmed == False:
                current.confirmed = True
                return 'confirmed'
            else:
                return 'already confirmed'
        else:
            if current.next is None:  # End of list?
                return 'not found'
            return self.confirm(name, start=current.next)


if __name__ == '__main__':

    vlist = VaccList()
    vlist.add_appt('Bob', 25, 'Tacoma', '2021-03-21')
    vlist.add_appt('Sue', 31, 'Seattle', '2021-03-22')
    vlist.add_appt('Ted', 28, 'Auburn', '2021-03-23')

    result = vlist.confirm('Sue')
    print('Sue is {}'.format(result))
    result = vlist.confirm('Sue')
    print('Sue is now {}'.format(result))

【讨论】:

  • 感谢您的完美工作!我真的很感激,我只是不确定如何使用递归并在到达最后一次约会时让它停止。
  • 是的,能够确定何时/如何停止是使用递归的一个关键方面,否则您将超过 Python 的最大递归限制(因为 stackoverflow ;¬)
  • 题外话:顺便说一句,一般来说,像这样的嵌套类在 Python 中几乎没有什么好处,实际上常常使事情变得尴尬并且更容易被破坏,因此通常被避免。
  • 是的,很多人都告诉过我,但我的教授出于某种原因希望这样设置。我也更喜欢使用单独的类。
  • 原因可能是由于它的少数优点之一,即encapsulation。然而,在“现实世界”场景中,VaccList 将在一个单独的模块中定义,从而允许将 Appointment 单独制作并仍被视为“捆绑”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-12
  • 1970-01-01
  • 1970-01-01
  • 2013-07-21
  • 1970-01-01
  • 1970-01-01
  • 2012-11-21
相关资源
最近更新 更多