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.










share|improve this question


























    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.










    share|improve this question
























      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.










      share|improve this question













      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






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 19 at 7:09









      Steve Strop

      112




      112
























          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.






          share|improve this answer























          • 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 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











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














           

          draft saved


          draft discarded


















          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

























          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.






          share|improve this answer























          • 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 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















          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.






          share|improve this answer























          • 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 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













          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.






          share|improve this answer














          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.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          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 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


















          • 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 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
















          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


















           

          draft saved


          draft discarded



















































           


          draft saved


          draft discarded














          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





















































          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







          Popular posts from this blog

          Ottavio Pratesi

          Tricia Helfer

          15 giugno