Невозможно объединить два отсортированных односвязных списка, поскольку «тип объекта« _Node »не имеет атрибута« _element »» - PullRequest
3 голосов
/ 09 апреля 2019

Я делаю свою собственную функцию merge_list.Я уже сделал класс SList () и класс _Node ().Но когда я ввожу два отсортированных списка в merge_list, функция merge_list не может сравнивать значения двух узлов, показывая type object '_Node' has no attribute '_element', но класс _Node имеет атрибут _element (я также пытаюсь использовать element, но он тоже не работает).Что не так с моей функцией ??

Это мой частичный код для class SList(), class _Node() и полный код merge_list

class SList:
    class _Node:
        def __init__(self, element, next=None):
            self._element = element
            self._next = next

        def element(self):
            return self._element

        def next(self):
            return self._next

        def set_element(self, element):
            self._element = element

        def set_next(self, next):
            self._next = next

    def __init__(self, head=None):
        self._head = head

    def insert_first(self, element):
        self._head = self._Node(element, self._head)

    def insert_after(self, element, p):
        new_node = self._Node(element, p.next())
        p._next = new_node



.,,и моя функция merge_list

def merge_list(s1, s2):
    s3 = SList()
    s3._Node(None, None)
    prev = s3

    while s1 != None and s2 != None:
        if s1._Node._element<= s2._Node._element: # this line is the problem
            prev.next = s1
            s1 = s1.next
        else:
            prev.next = s2
            s2 = s2.next
        prev = prev.next

    if s1 == None:
        prev.next = s2
    elif s2 == None:
        prev.next = s1

    return s3.next

После того, как я сделал эту функцию, я ввел два отсортированных списка, как это, и вызвал функцию merge_list

if __name__ == "__main__":
    s1 = SList()
    s1.insert_first(1)
    s1.insert_first(3)
    s1.insert_first(5)
    s1.insert_first(7)
    s1.insert_first(9)
    s1.insert_first(11)
    s1.insert_first(13)
    print(f"s1 :", s1)


    s2 = SList()
    s2.insert_first(2)
    s2.insert_first(4)
    s2.insert_first(6)
    print(f"s2 : ", s2)
    merge_list(s1, s2)

, и на выходе получилось

Traceback (most recent call last):
s1 : 13 -> 11 -> 9 -> 7 -> 5 -> 3 -> 1 -> None: 7 element(s)
s2 :  6 -> 4 -> 2 -> None: 3 element(s)
  File "", line 334, in <module>
    merge_list(s1, s2)
  File "", line 151, in merge_list
    if s1._Node._element<= s2._Node._element:
AttributeError: type object '_Node' has no attribute '_element'

Кажется, списки s1, s2 успешно созданы, но не могут сравнить значение узла.В чем проблема с функцией merge_list ??

1 Ответ

0 голосов
/ 09 апреля 2019

Пойдем шаг за шагом

Анализ кода:

class SList:
    class _Node:

note Зачем определять класс Node в классе SList?Это не обычная практика, если только вы никогда не захотите получить доступ к Узлу вне Slist (и даже тогда)

        def __init__(self, element, next=None):
            self._element = element
            self._next = next

        def element(self):
            return self._element

        def next(self):
            return self._next

        def set_element(self, element):
            self._element = element

        def set_next(self, next):
            self._next = next

note Инициаторы / получатели и установщики.До сих пор все имеет смысл.Однако я бы лично предпочел библиотеку @attrs.Но мы вернемся к этому позже.

    def __init__(self, head=None):
        self._head = head

    def insert_first(self, element):
        self._head = self._Node(element, self._head)

    def insert_after(self, element, p):
        new_node = self._Node(element, p.next())
        p._next = new_node


def merge_list(s1, s2):
    s3 = SList()
    s3._Node(None, None)
    prev = s3

    while s1 != None and s2 != None:
        if s1._Node._element<= s2._Node._element: # this line is the problem

Ну, это просто не будет работать по причинам, упомянутым в комментариях: класс _Node не имеет атрибута _element.Тем не менее, экземпляры делают.

            prev.next = s1

prev - это s3, то есть SList, поэтому не должно иметь следующего атрибута?

            s1 = s1.next
        else:
            prev.next = s2
            s2 = s2.next
        prev = prev.next

    if s1 == None:
        prev.next = s2
    elif s2 == None:
        prev.next = s1

    return s3.next

Первая попытка помочь (NB: Это рабочее решение, основанное на том, что предоставил OP, а не попытка написать чистый код.)

class _Node:
    def __init__(self, element, next=None):
        self._element = element
        self._next = next

    @property
    def element(self):
        return self._element
    @property
    def next(self):
        return self._next

    def set_element(self, element):
        self._element = element

    def set_next(self, next):
        self._next = next

class SList:
    def __init__(self, head=None):
        self._head = _Node(head)

    @property
    def head(self):
        return self._head 

    def insert_first(self, element):
        self._head = _Node(element, self._head)

    def insert_after(self, element, p):
        new_node = _Node(element, p.next())
        p._next = new_node

def merge_list(s1, s2):
    s3 = SList()
    prev = s3._head
    head_s1 = s1._head
    head_s2 = s2._head

    while (head_s1._element != None) and (head_s2._element != None):
        if head_s1._element<= head_s2._element: # this line is the problem
            prev.set_next(head_s1)
            head_s1 = head_s1.next
        else:
            prev.set_next(head_s2)
            head_s2 = head_s2.next
        prev = prev.next

    if head_s1 == None:
        prev.set_next(head_s1)
    elif head_s2 == None:
        prev.set_next(head_s2)

    return s3
...