创建双向链表类,我遇到了从列表中删除值的问题。我不确定如何修复__remove__
方法以使此代码正常工作。是否存在由于我的哨兵节点而未更新的循环?我尝试将其与我的__delitem__
身体相似,或者我应该尝试调用此方法?下面是我的课程代码。
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
### subscript-based access ###
def _normalize_idx(self, idx):
nidx = idx
if nidx < 0:
nidx += len(self)
if nidx < -1:
raise IndexError
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.head.next
if nidx >= len(self):
raise IndexError
for i in range(nidx):
currNode = currNode.next
currNode.val = 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):
currNode = currNode.next
currNode.prior.next = currNode.next #unlink currNode from its neighbors
currNode.next.prior = currNode.prior
self.length -= 1 #the del item has to decrease the size by 1 because of sentinel node
### single-element manipulation ###
def insert(self, idx, value):
"""Inserts value at position idx, shifting the original elements down the
list, as needed. Note that inserting a value at len(self) --- equivalent
to appending the value --- is permitted. Raises IndexError if idx is invalid."""
nidx = self._normalize_idx(idx)
currNode = self.head.next
for i in range(nidx):
currNode = currNode.next
newNode = LinkedList.Node(value, currNode.prior, currNode)
newNode.prior.next = newNode
currNode.prior = newNode
self.length += 1
def remove(self, value):
"""Removes the first (closest to the front) instance of value from the
list. Raises a ValueError if value is not found in the list."""
nidx = self._normalize_idx(0)
currNode = self.head.next
for i in range(nidx):
currNode = currNode.next
if currNode.val != value:
raise ValueError
elif currNode.val == value:
currNode.prior.next = currNode.next
currNode.next.prior = currNode.prior
self.length -= 1
def __len__(self):
"""Implements `len(self)`"""
return self.length
使用以下代码测试此类,我收到一条错误,说明789! = 653.调试器指向测试用例代码tc.assertEqual(data[i], lst[i])
中的一行,复制的数据似乎是迭代的:
# test single-element manipulation
from unittest import TestCase
import random
tc = TestCase()
lst = LinkedList()
data = []
for _ in range(100):
to_ins = random.randrange(1000)
ins_idx = random.randrange(len(data)+1)
data.insert(ins_idx, to_ins)
lst.insert(ins_idx, to_ins)
for _ in range(25):
to_rem = data[random.randrange(len(data))]
data.remove(to_rem)
lst.remove(to_rem)
for i in range(25):
tc.assertEqual(data[i], lst[i])
with tc.assertRaises(ValueError):
lst.remove(9999)
答案 0 :(得分:0)
您的问题是,for
循环永远不会运行,因为nidx
为零且range(0)
为空。您不需要此功能中的任何索引。只需使用一个while
循环,当你到达列表末尾时,就不会让你四处走动:
def remove(self, value):
"""Removes the first (closest to the front) instance of value from the
list. Raises a ValueError if value is not found in the list."""
currNode = self.head.next
while currNode != self.head:
if currNode.val == value:
currNode.prior.next = currNode.next
currNode.next.prior = currNode.prior
self.length -= 1
return
currNode = currNode.next
raise ValueError("Value not found")