FAQ: Linked Lists: Python - Linked Lists Implementation II

Right, but if we use repr then we can just print() instead of calling the function each time.

Is there any advantage to using the getter and setter methods over just referencing the class’s arguments?
For example, if you had to set a new “next_node” is there a difference between doing it like this:
my_node.next_node = new_next_node
or like this:
my_node.set_next_node(new_next_node)

Thanks!

Does anyone know why in this exercise they use the value as the parameter to check if we are at the end of the LinkedList instead of the actual pointer? I find it confusing, because the value of a node could actually be None right? While the pointer will be None for sure when we are at the tail of the LinkedList.

Another issue I am having is the actual code. Working with the .get_value() as the parameter to stop the While loop, I wrote the following:

def stringify_list(self):
    string_list = ""
    current_node = self.get_head_node()
    while current_node.get_value() != None:
      string_list += str(current_node.get_value()) + "/n"
      current_node = current_node.get_next_node()
    return string_list

The only difference with the solution is that I include the conditional directly onto the While loop line as opposed to setting an if statement afterwords. Why this doesn’t work? Thankss

That’s a good question. You are correct that one might find one or more nodes having a value of None. The solution works fine without any reference to the value of the next or current one. All that is needed is a check on the existence of next_node.

## From the "Solution"
(1)    while current_node:
(2)      if current_node.get_value() != None:   # This line is unnecessary
(3)        string_list += str(current_node.get_value()) + "\n"
(4)      current_node = current_node.get_next_node()   
(5)    return string_list
  • Line 2 does nothing but, as noted by @waiseheil, confuse things if you have a few nodes having a value of None.

  • Line 4 is key, since the __init__ method of node sets a default next_node as None … This (None) is next_node, it is not the value of next_node.

  • … So when we get to the node where n.get_next_node() returns None, that value None is assigned in line 4 to current_node, which terminates the while loop.


What do you mean by the pointer?


… because when you get to the end, as noted above, that final node is None, and you will see
AttributeError: 'NoneType' object has no attribute 'get_value'

2 Likes

hello folks. please help me out here coz I have been struggling with this code for a long while now.

`
class Node:
def init(self, value, next_node=None):
self.value = value
self.next_node = next_node

def get_value(self):
return self.value

def get_next_node(self):
return self.next_node

def set_next_node(self, next_node):
self.next_node = next_node

Our LinkedList class

class LinkedList:
def init(self, value=None):
self.head_node = Node(value)

def get_head_node(self):
return self.head_node

Add your insert_beginning and stringify_list methods below:

def insert_beginning(self, new_value):
new_node = Node(new_value)
new_node.set_next_node(self.head_node)
self.head_node = new_node

def stringify_list(self):
string_list = “”
current_node = self.get_head_node()
while current_node:
if current_node.get_value() != None:
string_list += str(current_node.get_value()) + “\n”
current_node = current_node.get_next_node()
return string_list

Test your code by uncommenting the statements below - did your list print to the terminal?

ll = LinkedList(5)
ll.insert_beginning(70)
ll.insert_beginning(5675)
ll.insert_beginning(90)
print(ll.stringify_list())
`

the confusing part is new_node.set_next_node(self.head_node) self.head_node = new_node . what is it that actually happened here. ‘new_node’ is an object of the node class. and I believe “new_value” passed when creating this object points to the “value” parameter of the Node class. and when we used “.set_next_node” method on the “new_node”, the “self.head_node” we passed as arguement represents what? is it the value of the Node class or that of the LinkedIn class.

please use the calls
"
ll = LinkedList(5)
ll.insert_beginning(70)
ll.insert_beginning(5675)
ll.insert_beginning(90)
print(ll.stringify_list()) " made on these object to explain. At what point did the arguement “5” passed become “value” of Node class and at which point did the other ones starting from “70” become “next_node” of the Node class. please help explain these things so that I can visualize them better. thanks famz for your help.

Hello dear, I love the explanations you gave here. but I just need some clarifications here. what exactly does " current_node = current_node.next_node" do here. I mean what exactly gets updasted to as “current_node” .? In the exercise, “insert_beginning” was used on “70, 5675, 90”. 90 was the last one and at that point, I believed “head_node” is now = (90, next_node), where the next_node is (5675, 70). so is current_node.next_node pointing to this particular (5675, 70) ? let me use the function so you understand better my confusion.

ll = LinkedList(5)
which means head_node is = (5, none)

insert_beginning(70)   
new_node = Node(70)
new_node.set_next_node(5, node)
self.head_node = (70, (5, none))

insert_beginning(5675)   
new_node = Node(5675)
new_node.set_next_node(70, 5))
self.head_node = (5675, (70, 5))

insert_beginning(90)
new_node = Node(90)
new_node.set_next_node(5675, 70)
self.head_node = (90, (5675, 70))

so using the stringify_list method, which next_node are they referring to when they called current_node = current_node.next_node ?

please help me solve this so I can visualize it better. I have been stuck here for weeks now. thanks.

Ehm. Doesn’t the expression say that?
current_node.next_node
If you have nodes numbered 0, 1, 2, … then the node after 347 is 348

I’d also argue that you should be able to execute it in year head or with pen and paper and observe what it makes you do. The code is the answer to your question, it says what it does, that’s what code is.

Or, if you’re going to avoid reading it, then consider what action is being implemented and how that would have to be done.
If you draw a small list on paper then you can do the operation manually and observe yourself.
(and if you don’t know how to draw a list then that’s the real problem, you would then want to first figure out what a list at all is before you start thinking about how to do operations on it)

it is okay. I only asked because I was confused. your answer did not help in any way. But I will continue to ask around. Thanks,.

Isn’t that what you’re asking though? “which node is the next node”

“the next node” is not a specific node, it’s the one that comes after the one you got it from

and if you repeatedly walk to the next node then you’ll have traveled several nodes

you can print it too, that’ll tell you specifically which one of your nodes it is.

linked lists can be executed on paper by drawing a circle for each node and having lines for links, you can follow the links to traverse the list, and you can move the links by crossing out/erasing and drawing new ones.

if you already know what your action should do then you already know … what it’s doing. or if you don’t, then figure that out before you start doing it with code, reasoning about the ideas doesn’t need to be in code it’ll only get in your way

thanks buddy… I really appreciate your response. you know sometimes, little codes can drive one crazy. The mystery has been solved. The truth was that I held complex things in my head, I just missed it at a point…and this “the next node” is not a specific node, it’s the one that comes after the one you got it from" helped me too.
Thanks again.

Thank you, that helped a lot!

After seeing your code I noticed I forgot to add a step to go to the next node, thus looping infinitely.

def stringify_list(self):
    string_list = ""
    current = self.get_head_node()
    while current:
      string_list += str(current.get_value()) + '\n'
      current = current.next_node
    return string_list  

worked for me