Learning to implement a queue in python 3 using a linked list
up vote
0
down vote
favorite
I've been struggling with this for a good while now. I've implemented a queue using a linked list. It's working fine, but I don't know why(?). I adapted the enqueue method from a java example but I can't work out why it's working.
class Node:
def __init__(self, data):
self.data = data
self.node= None
class Queue:
def __init__(self):
self.first = Node(None)
self.last = Node(None)
self.n = 0
def enqueue(self, data):
body = self.last
self.last = Node(data) # this is a new node
if self.is_empty():
self.first = self.last
else:
body.node = self.last # this adds body.node to self.first.node recursively ???? How is body node and self.first.node linked?
self.n += 1
def dequeue(self):
result = self.first.data
self.first = self.first.node
self.n -= 1
return result
def is_empty(self):
return self.n == 0
The problem is the enqueue method. I'm confused by the body variable. I've run the code through a pycharm debugger and carefully traced the three node variables self.first self.last and body. As the comments say, when body.node = self.last executes a new node object is attached to self.first.node recursively so that after three enqueue call I've got an object which looks like this: self.first.node.node.
Each node contains the appropriate data values and I can simply read them out of the queue with my dequeue method. (Happy days).
The problem is I cannot work out why. I can't see how body is programatically linked to self.first.
Can you please explain.
python linked-list queue
add a comment |
up vote
0
down vote
favorite
I've been struggling with this for a good while now. I've implemented a queue using a linked list. It's working fine, but I don't know why(?). I adapted the enqueue method from a java example but I can't work out why it's working.
class Node:
def __init__(self, data):
self.data = data
self.node= None
class Queue:
def __init__(self):
self.first = Node(None)
self.last = Node(None)
self.n = 0
def enqueue(self, data):
body = self.last
self.last = Node(data) # this is a new node
if self.is_empty():
self.first = self.last
else:
body.node = self.last # this adds body.node to self.first.node recursively ???? How is body node and self.first.node linked?
self.n += 1
def dequeue(self):
result = self.first.data
self.first = self.first.node
self.n -= 1
return result
def is_empty(self):
return self.n == 0
The problem is the enqueue method. I'm confused by the body variable. I've run the code through a pycharm debugger and carefully traced the three node variables self.first self.last and body. As the comments say, when body.node = self.last executes a new node object is attached to self.first.node recursively so that after three enqueue call I've got an object which looks like this: self.first.node.node.
Each node contains the appropriate data values and I can simply read them out of the queue with my dequeue method. (Happy days).
The problem is I cannot work out why. I can't see how body is programatically linked to self.first.
Can you please explain.
python linked-list queue
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I've been struggling with this for a good while now. I've implemented a queue using a linked list. It's working fine, but I don't know why(?). I adapted the enqueue method from a java example but I can't work out why it's working.
class Node:
def __init__(self, data):
self.data = data
self.node= None
class Queue:
def __init__(self):
self.first = Node(None)
self.last = Node(None)
self.n = 0
def enqueue(self, data):
body = self.last
self.last = Node(data) # this is a new node
if self.is_empty():
self.first = self.last
else:
body.node = self.last # this adds body.node to self.first.node recursively ???? How is body node and self.first.node linked?
self.n += 1
def dequeue(self):
result = self.first.data
self.first = self.first.node
self.n -= 1
return result
def is_empty(self):
return self.n == 0
The problem is the enqueue method. I'm confused by the body variable. I've run the code through a pycharm debugger and carefully traced the three node variables self.first self.last and body. As the comments say, when body.node = self.last executes a new node object is attached to self.first.node recursively so that after three enqueue call I've got an object which looks like this: self.first.node.node.
Each node contains the appropriate data values and I can simply read them out of the queue with my dequeue method. (Happy days).
The problem is I cannot work out why. I can't see how body is programatically linked to self.first.
Can you please explain.
python linked-list queue
I've been struggling with this for a good while now. I've implemented a queue using a linked list. It's working fine, but I don't know why(?). I adapted the enqueue method from a java example but I can't work out why it's working.
class Node:
def __init__(self, data):
self.data = data
self.node= None
class Queue:
def __init__(self):
self.first = Node(None)
self.last = Node(None)
self.n = 0
def enqueue(self, data):
body = self.last
self.last = Node(data) # this is a new node
if self.is_empty():
self.first = self.last
else:
body.node = self.last # this adds body.node to self.first.node recursively ???? How is body node and self.first.node linked?
self.n += 1
def dequeue(self):
result = self.first.data
self.first = self.first.node
self.n -= 1
return result
def is_empty(self):
return self.n == 0
The problem is the enqueue method. I'm confused by the body variable. I've run the code through a pycharm debugger and carefully traced the three node variables self.first self.last and body. As the comments say, when body.node = self.last executes a new node object is attached to self.first.node recursively so that after three enqueue call I've got an object which looks like this: self.first.node.node.
Each node contains the appropriate data values and I can simply read them out of the queue with my dequeue method. (Happy days).
The problem is I cannot work out why. I can't see how body is programatically linked to self.first.
Can you please explain.
python linked-list queue
python linked-list queue
asked Nov 19 at 7:09
Steve Strop
112
112
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
up vote
0
down vote
body is just a reference to self.last - that is the only place the assignment (body = self.last) occurs. This often has the name tmp or old_last or the like.
You need this since self.last is no longer referencing the last node in the queue, since self.last = Node(data). Now, since body is the old last, its node value was None (this is an invariant that has to be true - check it!). Since we do not want it to be last anymore, we set it to the new node we created - which is nicely referenced by self.last, which we just re-assigned. This is why body.node = self.last is right - the old last node is now pointing to the new last node (which is pointing to None, as we want).
There is nothing recursive here - just a temporary variable holding a reference to the old last.
When the queue is empty you get to:
self.first = self.last
which is where the node is first initialized (in enqueue). Note this means you have a minor bug, you lose the first reference in __init__ to the first Node(None), effectively a "memory leak" in other languages, but it matters little in Python.
The real bug is if you dequeue a new queue twice - try it. The first time will set first to None (which is not a Node), and the second will break since None has no data member.
Overall the implementation is flawed - I would redo it.
But at what point does first get updated with the contents of body?
– Steve Strop
Nov 19 at 8:17
@SteveStrop see edit.
– kabanus
Nov 19 at 10:49
Thanks for your help. I've fixed the dequeue issue by callingself.is_empty(). As far as the memory leak issue. I realise I don't need to define self.first in the init method but if I do then pycharm give me a style warning so I thought it was better to initialise it to None. Maybe that's not best practice?
– Steve Strop
Nov 19 at 12:37
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
body is just a reference to self.last - that is the only place the assignment (body = self.last) occurs. This often has the name tmp or old_last or the like.
You need this since self.last is no longer referencing the last node in the queue, since self.last = Node(data). Now, since body is the old last, its node value was None (this is an invariant that has to be true - check it!). Since we do not want it to be last anymore, we set it to the new node we created - which is nicely referenced by self.last, which we just re-assigned. This is why body.node = self.last is right - the old last node is now pointing to the new last node (which is pointing to None, as we want).
There is nothing recursive here - just a temporary variable holding a reference to the old last.
When the queue is empty you get to:
self.first = self.last
which is where the node is first initialized (in enqueue). Note this means you have a minor bug, you lose the first reference in __init__ to the first Node(None), effectively a "memory leak" in other languages, but it matters little in Python.
The real bug is if you dequeue a new queue twice - try it. The first time will set first to None (which is not a Node), and the second will break since None has no data member.
Overall the implementation is flawed - I would redo it.
But at what point does first get updated with the contents of body?
– Steve Strop
Nov 19 at 8:17
@SteveStrop see edit.
– kabanus
Nov 19 at 10:49
Thanks for your help. I've fixed the dequeue issue by callingself.is_empty(). As far as the memory leak issue. I realise I don't need to define self.first in the init method but if I do then pycharm give me a style warning so I thought it was better to initialise it to None. Maybe that's not best practice?
– Steve Strop
Nov 19 at 12:37
add a comment |
up vote
0
down vote
body is just a reference to self.last - that is the only place the assignment (body = self.last) occurs. This often has the name tmp or old_last or the like.
You need this since self.last is no longer referencing the last node in the queue, since self.last = Node(data). Now, since body is the old last, its node value was None (this is an invariant that has to be true - check it!). Since we do not want it to be last anymore, we set it to the new node we created - which is nicely referenced by self.last, which we just re-assigned. This is why body.node = self.last is right - the old last node is now pointing to the new last node (which is pointing to None, as we want).
There is nothing recursive here - just a temporary variable holding a reference to the old last.
When the queue is empty you get to:
self.first = self.last
which is where the node is first initialized (in enqueue). Note this means you have a minor bug, you lose the first reference in __init__ to the first Node(None), effectively a "memory leak" in other languages, but it matters little in Python.
The real bug is if you dequeue a new queue twice - try it. The first time will set first to None (which is not a Node), and the second will break since None has no data member.
Overall the implementation is flawed - I would redo it.
But at what point does first get updated with the contents of body?
– Steve Strop
Nov 19 at 8:17
@SteveStrop see edit.
– kabanus
Nov 19 at 10:49
Thanks for your help. I've fixed the dequeue issue by callingself.is_empty(). As far as the memory leak issue. I realise I don't need to define self.first in the init method but if I do then pycharm give me a style warning so I thought it was better to initialise it to None. Maybe that's not best practice?
– Steve Strop
Nov 19 at 12:37
add a comment |
up vote
0
down vote
up vote
0
down vote
body is just a reference to self.last - that is the only place the assignment (body = self.last) occurs. This often has the name tmp or old_last or the like.
You need this since self.last is no longer referencing the last node in the queue, since self.last = Node(data). Now, since body is the old last, its node value was None (this is an invariant that has to be true - check it!). Since we do not want it to be last anymore, we set it to the new node we created - which is nicely referenced by self.last, which we just re-assigned. This is why body.node = self.last is right - the old last node is now pointing to the new last node (which is pointing to None, as we want).
There is nothing recursive here - just a temporary variable holding a reference to the old last.
When the queue is empty you get to:
self.first = self.last
which is where the node is first initialized (in enqueue). Note this means you have a minor bug, you lose the first reference in __init__ to the first Node(None), effectively a "memory leak" in other languages, but it matters little in Python.
The real bug is if you dequeue a new queue twice - try it. The first time will set first to None (which is not a Node), and the second will break since None has no data member.
Overall the implementation is flawed - I would redo it.
body is just a reference to self.last - that is the only place the assignment (body = self.last) occurs. This often has the name tmp or old_last or the like.
You need this since self.last is no longer referencing the last node in the queue, since self.last = Node(data). Now, since body is the old last, its node value was None (this is an invariant that has to be true - check it!). Since we do not want it to be last anymore, we set it to the new node we created - which is nicely referenced by self.last, which we just re-assigned. This is why body.node = self.last is right - the old last node is now pointing to the new last node (which is pointing to None, as we want).
There is nothing recursive here - just a temporary variable holding a reference to the old last.
When the queue is empty you get to:
self.first = self.last
which is where the node is first initialized (in enqueue). Note this means you have a minor bug, you lose the first reference in __init__ to the first Node(None), effectively a "memory leak" in other languages, but it matters little in Python.
The real bug is if you dequeue a new queue twice - try it. The first time will set first to None (which is not a Node), and the second will break since None has no data member.
Overall the implementation is flawed - I would redo it.
edited Nov 19 at 10:49
answered Nov 19 at 7:17
kabanus
10.8k21237
10.8k21237
But at what point does first get updated with the contents of body?
– Steve Strop
Nov 19 at 8:17
@SteveStrop see edit.
– kabanus
Nov 19 at 10:49
Thanks for your help. I've fixed the dequeue issue by callingself.is_empty(). As far as the memory leak issue. I realise I don't need to define self.first in the init method but if I do then pycharm give me a style warning so I thought it was better to initialise it to None. Maybe that's not best practice?
– Steve Strop
Nov 19 at 12:37
add a comment |
But at what point does first get updated with the contents of body?
– Steve Strop
Nov 19 at 8:17
@SteveStrop see edit.
– kabanus
Nov 19 at 10:49
Thanks for your help. I've fixed the dequeue issue by callingself.is_empty(). As far as the memory leak issue. I realise I don't need to define self.first in the init method but if I do then pycharm give me a style warning so I thought it was better to initialise it to None. Maybe that's not best practice?
– Steve Strop
Nov 19 at 12:37
But at what point does first get updated with the contents of body?
– Steve Strop
Nov 19 at 8:17
But at what point does first get updated with the contents of body?
– Steve Strop
Nov 19 at 8:17
@SteveStrop see edit.
– kabanus
Nov 19 at 10:49
@SteveStrop see edit.
– kabanus
Nov 19 at 10:49
Thanks for your help. I've fixed the dequeue issue by calling
self.is_empty(). As far as the memory leak issue. I realise I don't need to define self.first in the init method but if I do then pycharm give me a style warning so I thought it was better to initialise it to None. Maybe that's not best practice?– Steve Strop
Nov 19 at 12:37
Thanks for your help. I've fixed the dequeue issue by calling
self.is_empty(). As far as the memory leak issue. I realise I don't need to define self.first in the init method but if I do then pycharm give me a style warning so I thought it was better to initialise it to None. Maybe that's not best practice?– Steve Strop
Nov 19 at 12:37
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53369845%2flearning-to-implement-a-queue-in-python-3-using-a-linked-list%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown