5

If I have created a linked list of nodes which have a value attribute, is there a way to print all value attributes for all nodes in the linked list using a while loop?

[Edit] Also, how might I invoke the iter magic method so that I can iterate and print over the linked list? How also might I create a method that allows for additions, at the beginning, end, or before or after a certain object?

(I apologize if there is something basic, conceptually, that I'm missing in my understanding)

Below is the code for the nodes and singly linked list I've got setup, and you'll see that I've printed each value for each node at the bottom. However, I wasn't sure if there was a simple way to print all values easily, rather than listing each one:

# node class
class Node(object):
    def __init__(self, value):
        self.value = value
        self.next = None

# singly linked list class
class SinglyLinkedList(object):
    def __init__(self):
        self.head = None
        self.tail = None

linked_list = SinglyLinkedList()
linked_list.head = Node('Alice')
linked_list.head.next = Node('Chad')
linked_list.head.next.next = Node('Debra')

print linked_list.head.value, linked_list.head.next.value, linked_list.head.next.next.value
# is there a way to print all values for `linked_list` easily?

Thank you Stack Community for your help and for reading!

twknab
  • 1,741
  • 1
  • 21
  • 35

2 Answers2

15

You can use a while loop, setting a variable to the head at first and the next node on each iteration:

node = linked_list.head
while node:
    print node.value
    node = node.next

A few other suggestions for your implementation:

1) Don't use list as a variable name. It's a sequence type in Python.

2) Don't forget to set tail!

3) If you want to be fancy, you can implement __iter__ on your linked list to make it iterable. You can also implement an add method so that it's easier to add new items to your list. Here's an example implementation:

class Node(object):
    def __init__(self, value):
        self.value = value
        self.next = None

class SinglyLinkedList(object):
    def __init__(self):
        self.head = None
        self.tail = None

    def __iter__(self):
        node = linked_list.head
        while node:
            yield node
            node = node.next

    def add(self, node):
        if self.head:
            self.tail.next = node
        else:
            self.head = node

        self.tail = node

linked_list = SinglyLinkedList()
linked_list.add(Node('Alice'))
linked_list.add(Node('Chad'))
linked_list.add(Node('Debra'))

print [node.value for node in linked_list]  # ['Alice', 'Chad', 'Debra']
Karin
  • 8,404
  • 25
  • 34
  • It would be much easier if you inherit from the list object. You would not need to define the add method. And you can also use all the method in a normal list. – Riccardo Petraglia Sep 20 '16 at 04:55
  • I think that negates one of the biggest advantages of a linked list, which is `O(1)` list insertion/deletion given a node as opposed to `O(n)`. – Karin Sep 20 '16 at 04:58
  • ok, I understand... – Riccardo Petraglia Sep 20 '16 at 05:00
  • @Karin : this was all very very helpful - thank you for posting the further and expanded explanations. Providing me with the additional [__iter__ magic method example][1], this was super helpful. If I do set a tail, how then can I print the full list, including the tail? I see the while loop snippet shared only prints head object values, is that correct? (I am having the same issue with the iterations, where everything but the tail is being printed). Thank you greatly for your help! [1]: http://ironpythoninaction.com/magic-methods.html – twknab Sep 20 '16 at 05:43
-1

OPSSSS: The following is not a linked list! Use it as an example of something wrong! ;)

Your list is actually missing the method next. Each time you assign something using the method next you are creating a variable called something.next. The your, is not a real list, is only an ensemble of variables.

I think you should implement a class like the following:

class SinglyLinkedList(list):
    def __init__(self, *args, **kwd):
        super(SinglyLinkedList, self).__init__(*args, **kwd)

    def head(self):
        self.counter = 0
        return self[0]

    def tail(self):
        self.counter = len(self)
        return self[-1]

    def next(self):
        self.counter += 1
        return self[self.counter]

    def previous(self):
        self.counter -=1
        return self[self.counter]

newlist = SinglyLinkedList([1,2,3,4])
newlist.head()
# 1
newlist.tail()
# 4
newlist.head().next()
# 2
newlist.previous()
# 1
# you can print using any method you would use in for a list
Riccardo Petraglia
  • 1,943
  • 1
  • 13
  • 25