[英]How do I set the prev of my first node to the next of my last node to create a circular doubly linked list?
I am creating the Josephus problem using a circular doubly linked list.我正在使用循环双向链表创建 Josephus 问题。 I am getting an Attribute error, which I assume is because my current_node (first node) does not have a .prev yet.
我收到一个属性错误,我认为这是因为我的 current_node(第一个节点)还没有 .prev。
I understand that the prev of my first node should point to the next of my last node to create a circular doubly linked list.我知道我的第一个节点的上一个节点应该指向我最后一个节点的下一个节点来创建一个循环双向链表。
Can someone guide me on whether I have correctly identified the error?有人可以指导我是否正确识别错误? If yes, how can I rectify it?
如果是,我该如何纠正?
If not, then what are the other ways I can correct the error?如果没有,那么我可以纠正错误的其他方法是什么?
#Initialize the node
def __init__(self, data):
self.data = data
self.next = None
self.prev = None
def remove(self, n):
print("Student " +str(n)+ " was removed")
class Circle:
# Initializing the DLL
def __init__(self):
self.head = None
self.tail = None
#Inserting elements 2 to n in the dll
def insert_after(self, x, data):
y = Student(data) # make a new Node object.
z = Student(data)
z = x.next
y.prev = x
y.next = z
x.next = y
z.prev = y
def josephus_solution(self, dllist, n, k):
no_of_active_nodes = n
current_node = Student(1)
#last_node = Student(n)
#print(current_node.prev)
for i in range(2, n + 1):
dllist.insert_after(current_node, i)
count = 0
#print(current_node.data)
while (current_node.next != current_node.prev):
#print(current_node.next.prev)
current_node = current_node.next
count += 1
#print(current_node.data)
if (count == k):
current_node.remove(current_node.data)
current_node.prev.next = current_node.next
current_node.next.prev = current_node.prev
count = 0
no_of_active_nodes -= 1
#print(no_of_active_nodes)
if (no_of_active_nodes == 1):
print("Student" + str(current_node.data) + "Recieves the scholarship")
return current_node.data
dllist = Circle()
n = 5 #int(input('Input number of people (n): '))
k = 2 #int(input('The nth person will be executed. Input k: '))
ans = dllist.josephus_solution(dllist, n, k)
Error错误
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
/tmp/ipykernel_24/3762059582.py in <module>
54 n = 5 #int(input('Input number of people (n): '))
55 k = 2 #int(input('The nth person will be executed. Input k: '))
---> 56 ans = dllist.josephus_solution(dllist, n, k)
/tmp/ipykernel_24/3762059582.py in josephus_solution(self, dllist, n, k)
32 #print(current_node.prev)
33 for i in range(2, n + 1):
---> 34 dllist.insert_after(current_node, i)
35 count = 0
36 #print(current_node.data)
/tmp/ipykernel_24/3762059582.py in insert_after(self, x, data)
24 x.next = y
25
---> 26 z.prev = y
27
28 def josephus_solution(self, dllist, n, k):
AttributeError: 'NoneType' object has no attribute 'prev'
The direct reason for the error is that z
is None
and your code can therefore not access any prev
attribute of it in the line z.prev = y
.错误的直接原因是
z
是None
,因此您的代码无法在z.prev = y
行中访问它的任何prev
属性。 The cause is that when the first node is created, its prev
and next
attributes are initialised to None
, and when this node is passed as x
argument to insert_after
, then with z = x.next
a None
value is assigned to z
.原因是当第一个节点被创建时,它的
prev
和next
属性被初始化为None
,当这个节点作为x
参数传递给insert_after
,然后z = x.next
一个None
值被分配给z
。
There are several issues with your approach:你的方法有几个问题:
insert_after
it makes no sense to call Student
twice, since you want to insert one node, not twoinsert_after
中调用Student
两次是没有意义的,因为你想插入一个节点,而不是两个Circle
class has a head
and a tail
attribute, they are never used after their initialisation to None
, so there is actually nothing in the Circle instance that helps you to maintain the list.Circle
类有一个head
和一个tail
属性,但它们在初始化为None
后就不再使用了,因此 Circle 实例中实际上没有任何内容可以帮助您维护列表。 You might as well define all methods on the Student
class.Student
类上定义所有方法。josephus_solution
is probably intended to test that only one node remains in the list, but it actually verifies whether there are two left. josephus_solution
的 while 条件可能是为了测试列表中只剩下一个节点,但它实际上是验证是否还剩下两个节点。 Admittedly, this works when current_node
is a node that was just deleted, but then the returned data is the data of the deleted node and not the remaining active node, and current_node
is not a just-deleted node, then this condition will make the loop exit when it still has two active nodes.current_node
是刚删除的节点时,这是有效的,但是返回的数据是被删除节点的数据而不是剩余的活动节点,并且current_node
不是刚删除的节点,那么这种情况将使循环当它还有两个活动节点时退出。 Some other remarks:其他一些注意事项:
josephus_solution
as a method, it should not be necessary to also pass an instance as argument.josephus_solution
作为方法调用时,也不必将实例作为参数传递。 self
is already available to that method self
已经可用于该方法josephus_solution
work on an existing linked list.josephus_solution
处理现有的链表。next
or prev
attributes should ever be None
, you'll make things easier when initialising them to self
instead of None
.next
或prev
属性都不应该是None
,当将它们初始化为self
而不是None
时,您会让事情变得更容易。remove
method should not be responsible for printing a message, but should on the other hand be responsible for rewiring the prev
and next
references.remove
方法不应该负责打印的消息,而是应该在另一方面负责重新布线的prev
和next
引用。 At any rate, there is no need for this method to get an argument, as it knows its own attributes through self
.self
知道自己的属性。current_node = current_node.next
statement to be the last line in the body of the loop.current_node = current_node.next
语句是循环体中的最后一行。 This also helps to be sure that current_node
is never a just-deleted node when the while
condition is evaluated.while
条件时current_node
永远不会是刚刚删除的节点。while
condition already takes care of when to stop, there should be no reason to keep track with a no_of_active_nodes
variable.while
条件已经处理了何时停止,因此没有理由使用no_of_active_nodes
变量进行跟踪。 There are more remarks to make, but these are what I believe the most important.还有更多的评论要说,但这些是我认为最重要的。
Here is a correction of your code, taking all of the above into account:考虑到以上所有因素,以下是对您的代码的更正:
class Student:
def __init__(self, data):
self.data = data
# Better make prev/next self references to avoid None:
self.next = self
self.prev = self
def remove(self):
# Perform the remove here
self.prev.next = self.next
self.next.prev = self.prev
def insert(self, data):
# Should only create one node, not two
node = Student(data)
node.next = self
node.prev = self.prev
self.prev = node.prev.next = node
# Handy method to create a circular list from values
@classmethod
def fromiterator(cls, iterator):
head = cls(next(iterator))
for value in iterator:
head.insert(value)
return head
def josephus_solution(self, k):
count = 0
current_node = self
while current_node.next is not current_node: # This is how to test for 1 node
count += 1
if count == k:
current_node.remove() # No argument
print("Student " +str(current_node.data) + " was removed")
count = 0
current_node = current_node.next # do this at the end of the iteration
# No need to keep track of active nodes ...
return current_node
# These are the parameters of the "original" problem (see Wikipedia)
n = 41
k = 3
dllist = Student.fromiterator(iter(range(1, n+1)))
# Don't pass the list as argument: it already is available as `self`
dllist = dllist.josephus_solution(k)
# Perform output in the main code, not inside method
print("Student " + str(dllist.data) + " recieves the scholarship")
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.