+ 3.3_07
This commit is contained in:
parent
fb4a932136
commit
360f71e61e
172
mod_oop/3.3_07_linkedlist.py
Normal file
172
mod_oop/3.3_07_linkedlist.py
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
"""
|
||||||
|
https://stepik.org/lesson/701988/step/7?unit=702089
|
||||||
|
|
||||||
|
Объявите класс LinkedList (связный список) для работы со следующей структурой данных:
|
||||||
|
|
||||||
|
Здесь создается список из связанных между собой объектов класса ObjList. Объекты этого класса создаются командой:
|
||||||
|
|
||||||
|
obj = ObjList(data)
|
||||||
|
где data - строка с некоторой информацией. Также в каждом объекте obj класса ObjList должны создаваться следующие локальные атрибуты:
|
||||||
|
|
||||||
|
__data - ссылка на строку с данными;
|
||||||
|
__prev - ссылка на предыдущий объект связного списка (если объекта нет, то __prev = None);
|
||||||
|
__next - ссылка на следующий объект связного списка (если объекта нет, то __next = None).
|
||||||
|
|
||||||
|
В свою очередь, объекты класса LinkedList должны создаваться командой:
|
||||||
|
|
||||||
|
linked_lst = LinkedList()
|
||||||
|
и содержать локальные атрибуты:
|
||||||
|
|
||||||
|
head - ссылка на первый объект связного списка (если список пуст, то head = None);
|
||||||
|
tail - ссылка на последний объект связного списка (если список пуст, то tail = None).
|
||||||
|
|
||||||
|
А сам класс содержать следующие методы:
|
||||||
|
|
||||||
|
add_obj(obj) - добавление нового объекта obj класса ObjList в конец связного списка;
|
||||||
|
remove_obj(indx) - удаление объекта класса ObjList из связного списка по его порядковому номеру (индексу); индекс отсчитывается с нуля.
|
||||||
|
|
||||||
|
Также с объектами класса LinkedList должны поддерживаться следующие операции:
|
||||||
|
|
||||||
|
len(linked_lst) - возвращает число объектов в связном списке;
|
||||||
|
linked_lst(indx) - возвращает строку __data, хранящуюся в объекте класса ObjList, расположенного под индексом indx (в связном списке).
|
||||||
|
|
||||||
|
Пример использования классов (эти строчки в программе писать не нужно):
|
||||||
|
|
||||||
|
linked_lst = LinkedList()
|
||||||
|
linked_lst.add_obj(ObjList("Sergey"))
|
||||||
|
linked_lst.add_obj(ObjList("Balakirev"))
|
||||||
|
linked_lst.add_obj(ObjList("Python"))
|
||||||
|
linked_lst.remove_obj(2)
|
||||||
|
linked_lst.add_obj(ObjList("Python ООП"))
|
||||||
|
n = len(linked_lst) # n = 3
|
||||||
|
s = linked_lst(1) # s = Balakirev
|
||||||
|
P.S. На экран в программе ничего выводить не нужно.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class LinkedList:
|
||||||
|
def __init__(self):
|
||||||
|
self.head = None
|
||||||
|
self.tail = None
|
||||||
|
|
||||||
|
def add_obj(self, obj):
|
||||||
|
if not self.head:
|
||||||
|
self.head = obj
|
||||||
|
self.tail = obj
|
||||||
|
else:
|
||||||
|
self.tail.next = obj
|
||||||
|
obj.prev = self.tail
|
||||||
|
self.tail = obj
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
obj = self.head
|
||||||
|
while obj and obj != self.tail.next:
|
||||||
|
yield obj
|
||||||
|
obj = obj.next
|
||||||
|
|
||||||
|
def __reversed__(self):
|
||||||
|
obj = self.tail
|
||||||
|
while obj and obj != self.head.prev:
|
||||||
|
yield obj
|
||||||
|
obj = obj.prev
|
||||||
|
|
||||||
|
def remove_obj(self, idx):
|
||||||
|
if not self:
|
||||||
|
pass
|
||||||
|
elif idx == 0:
|
||||||
|
self.head = self.head.next
|
||||||
|
if self.head:
|
||||||
|
self.head.prev = None
|
||||||
|
elif idx == len(self) - 1:
|
||||||
|
self.tail = self.tail.prev
|
||||||
|
self.tail.next = None
|
||||||
|
else:
|
||||||
|
obj = self.head
|
||||||
|
for _ in range(idx):
|
||||||
|
obj = obj.next
|
||||||
|
obj.prev.next = obj.next
|
||||||
|
obj.next.prev = obj.prev
|
||||||
|
|
||||||
|
if not self:
|
||||||
|
self.head = self.tail = None
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return sum(1 for _ in self)
|
||||||
|
|
||||||
|
def __getitem__(self, idx):
|
||||||
|
return next(filter(lambda x: x[0] == idx, enumerate(self)))[1]
|
||||||
|
|
||||||
|
def __call__(self, key):
|
||||||
|
return self[key].data
|
||||||
|
|
||||||
|
def get_data(self):
|
||||||
|
return [*map(ObjList.get_data, self)]
|
||||||
|
|
||||||
|
|
||||||
|
class ObjList:
|
||||||
|
def __init__(self, data=None):
|
||||||
|
self.__next = None
|
||||||
|
self.__prev = None
|
||||||
|
self.__data = data
|
||||||
|
|
||||||
|
def set_next(self, obj):
|
||||||
|
self.__next = obj
|
||||||
|
|
||||||
|
def set_prev(self, obj):
|
||||||
|
self.__prev = obj
|
||||||
|
|
||||||
|
def get_next(self):
|
||||||
|
return self.__next
|
||||||
|
|
||||||
|
def get_prev(self):
|
||||||
|
return self.__prev
|
||||||
|
|
||||||
|
def set_data(self, data):
|
||||||
|
self.__data = data
|
||||||
|
|
||||||
|
def get_data(self):
|
||||||
|
return self.__data
|
||||||
|
|
||||||
|
data = property(get_data, set_data)
|
||||||
|
next = property(get_next, set_next)
|
||||||
|
prev = property(get_prev, set_prev)
|
||||||
|
|
||||||
|
|
||||||
|
def tests():
|
||||||
|
ln = LinkedList()
|
||||||
|
ln.add_obj(ObjList("Сергей"))
|
||||||
|
ln.add_obj(ObjList("Балакирев"))
|
||||||
|
ln.add_obj(ObjList("Python ООП"))
|
||||||
|
ln.remove_obj(2)
|
||||||
|
assert (
|
||||||
|
len(ln) == 2
|
||||||
|
), "функция len вернула неверное число объектов в списке, возможно, неверно работает метод remove_obj()"
|
||||||
|
ln.add_obj(ObjList("Python"))
|
||||||
|
assert ln(2) == "Python", "неверное значение атрибута __data, взятое по индексу"
|
||||||
|
assert len(ln) == 3, "функция len вернула неверное число объектов в списке"
|
||||||
|
assert ln(1) == "Балакирев", "неверное значение атрибута __data, взятое по индексу"
|
||||||
|
|
||||||
|
n = 0
|
||||||
|
h = ln.head
|
||||||
|
while h:
|
||||||
|
assert isinstance(h, ObjList)
|
||||||
|
h = h._ObjList__next
|
||||||
|
n += 1
|
||||||
|
|
||||||
|
assert n == 3, "при перемещении по списку через __next не все объекты перебрались"
|
||||||
|
|
||||||
|
n = 0
|
||||||
|
h = ln.tail
|
||||||
|
while h:
|
||||||
|
assert isinstance(h, ObjList)
|
||||||
|
h = h._ObjList__prev
|
||||||
|
n += 1
|
||||||
|
|
||||||
|
assert n == 3, "при перемещении по списку через __prev не все объекты перебрались"
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import doctest
|
||||||
|
|
||||||
|
doctest.testmod()
|
||||||
|
tests()
|
Loading…
Reference in New Issue
Block a user