2016-06-11 3 views
0

Я создаю класс LinkedList, чтобы лучше понять язык python и его дважды связанные узлы. Моя общая задача состоит в том, чтобы не использовать встроенную структуру данных списка python, а также пытаться оптимизировать эффективность времени кода. Какой был бы лучший способ решить, что я буду считать, это мой getitem или setitem способ тело.Устранение неполадок ошибки?

class LinkedList: 
    class Node: 
     def __init__(self, val, prior=None, next=None): 
      self.val = val 
      self.prior = prior 
      self.next = next 

    def __init__(self): 
     self.head = LinkedList.Node(None) # sentinel node (never to be removed) 
     self.head.prior = self.head.next = self.head # set up "circular" topology 
     self.length = 0 


### prepend and append 

    def prepend(self, value): 
     n = LinkedList.Node(value, prior=self.head, next=self.head.next) 
     self.head.next.prior = self.head.next = n 
     self.length += 1 

    def append(self, value): 
     n = LinkedList.Node(value, prior=self.head.prior, next=self.head) 
     n.prior.next = n.next.prior = n 
     self.length += 1 


### subscript-based access ### 

    def _normalize_idx(self, idx): 
     nidx = idx 
     if nidx < 0: 
      nidx += len(self) 
      if nidx < 0: 
       nidx = 0 
     return nidx 

    def __getitem__(self, idx): 
     """Implements `x = self[idx]`""" 
     nidx = self._normalize_idx(idx) 
     currNode = self.head.next 
     for i in range(nidx): 
      currNode = currNode.next 
     if nidx >= len(self): 
      raise IndexError 
     return currNode.val 


    def __setitem__(self, idx, value): 
     """Implements `self[idx] = x`""" 
     nidx = self._normalize_idx(idx) 
     currNode = self[nidx] 
     if nidx >= len(self): 
      raise IndexError 
     currNode = value 

    def __delitem__(self, idx): 
     """Implements `del self[idx]`""" 
     nidx = self._normalize_idx(idx) 
     currNode = self.head.next 
     if nidx >= len(self): 
      raise IndexError 
     for i in range(nidx+1, len(self)): 
      self[i-1] = self[i] 
     del self[len(self)-1] 

Тестирование этот код с помощью:

# test subscript-based access 
from unittest import TestCase 
import random 

tc = TestCase() 
data = [1, 2, 3, 4] 
lst = LinkedList() 
for d in data: 
    lst.append(d) 

for i in range(len(data)): 
    tc.assertEqual(lst[i], data[i]) 

with tc.assertRaises(IndexError): 
    x = lst[100] 

with tc.assertRaises(IndexError): 
    lst[100] = 0 

with tc.assertRaises(IndexError): 
    del lst[100] 

lst[1] = data[1] = 20 
del data[0] 
del lst[0] 

for i in range(len(data)): 
    tc.assertEqual(lst[i], data[i]) 

я получаю сообщение об ошибке говорящее 1 = 20. Написание этих методов класса всегда кажется мне подножку вверх, что может я не хватать!? Я не совсем уверен, как это отличается от типичного массива, поддерживаемого списком. И я не уверен, откуда эта стоимость 20.

ответ

1

я получаю сообщение об ошибке говорящее 1! = 20

Это истинное утверждение, хотя, так что ваша проблема существует в том, как установить данные списка. Он не обновлялся, но список Python был.

Я не уверен, где это 20 значение поступает из

Умм ... lst[1] = data[1] = 20, возможно?

В любом случае, я не думаю, что ваша функция setItem верна. Переменная curNode есть только значение, а не ссылка на объект Node на основе метода getItem, поэтому currNode = value фактически не обновляет список, а только локальную переменную, привязанную к этой функции.

+0

Я думаю, я не уверен, как установить элемент по указанному индексу. Если бы я изменил код, добавив что-то вроде 'currNode = self.head [nidx]', я получу ошибку, но я не уверен, как еще идентифицировать нужный узел. –

+0

Вам придется перебирать список объектов узла, как вы это делали с помощью getItem. Затем вместо 'return curNode.val' вы устанавливаете его значение. –

Смежные вопросы