Python Forum

Full Version: How to create a linked list and call it?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
I want to create a linked list and insert dummy data to verify it. Please see my code.
class ListNode:
     def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
     a = ListNode(2)
     a.next = ListNode(4)
     a.next.next = ListNode(3)
     print(a)
So I want to insert 2,4 and 3. Is the code right?
Why do you want to make a linked list? Python lists are pretty efficient and do all the things you normally do with a C type list and much more. Your example would be:
a = [2, 4, 3]
It is a Letcode problem. https://leetcode.com/problems/add-two-numbers/
I can't print the result as expected. I got the result as <__main__.ListNode object at 0x000001F595801190> in Spyder.
Start by writing a function that prints all the values in your linked list. Once you have that, you can use it for debugging.

Have the function create an empty list. Then append the node's value and see if there's a next node. When complete, print out the list.
(Nov-20-2020, 11:23 PM)loves Wrote: [ -> ]It is a Letcode problem. https://leetcode.com/problems/add-two-numbers/
I can't print the result as expected. I got the result as <__main__.ListNode object at 0x000001F595801190> in Spyder.

To make it easy to print out, also implement the __repr__ method: https://dbader.org/blog/python-repr-vs-str
I got an error AttributeError: 'int' object has no attribute 'val'.
I am a python beginner and could you please correct my code instead of comments.

Many thanks.
class ListNode:
     def __init__(self, val = 0, next = None):
        self.val = val
        self.next = next
        
     def listprint(self):
        printval = self.val
        while printval is not None:
            print (printval.val)
            printval = printval.next   
       
class Solution:
               
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        integerL1 = ""
        integerL2 = ""
        curL1 = l1
        curL2 = l2
        while curL1 is not None or curL2 is not None:
            if curL1 is not None:
                integerL1 += str(curL1.val)
                curL1 = curL1.next
            if curL2 is not None:
                integerL2 += str(curL2.val)
                curL2 = curL2.next
        integerL1 = integerL1[::-1]
        integerL2 = integerL2[::-1]
        integerL1 = int(integerL1)
        integerL2 = int(integerL2)
        combine = integerL1 + integerL2
        combine = str(combine)
        combine = combine[::-1]
        main = l1
        headOne = True
        for i in range(len(combine)):
            if headOne:
                t = int(combine[i])
                print(t)
                l1 = ListNode(t)
                print(l1.val)
                main = l1
                headOne = False
                continue
            if main.next is None:
                p = int(combine[i])
                main.next = ListNode(p)
                main = main.next

        return main
    
list1 = ListNode(2);
list1.next = ListNode(4)
list1.next.next = ListNode(3)
list2 = ListNode(5);
list2.next = ListNode(6)
list2.next.next = ListNode(4) 
s = Solution()  
merge = s.addTwoNumbers(list1, list2)

merge.listprint()
I used itertools zip to zip the lists together. To allow for uneven sized lists I used the zip_longest version. Because the LList naturally builds backwards I need to reverse the list when done so it is in the correct order (least significant digit is first).

For printing I added a __repr__ method to LList. I also added some convenience functions that are commonly provided by collection types.
import itertools

class LList:
    def __init__(self, value=0, nxt=None):
        self.value = value
        self.nxt = nxt

    def values(self):
        """Generator for getting all the values"""
        ptr = self
        while ptr:
            yield ptr.value
            ptr = ptr.nxt

    def reverse(self):
        """Make new LList with order of values reversed"""
        result = None
        while self:
            result = LList(self.value, result)
            self = self.nxt
        return result

    def __len__(self):
        """Return number of values in LList"""
        count = 0
        ptr = self
        while ptr is not None:
            count += 1
            ptr = ptr.nxt
        return count

    def __getitem__(self, index):
        """Get value by index: LList[index]"""
        ptr = self
        for _ in range(index):
            ptr = ptr.nxt
        return ptr.value

    def __setitem__(self, index, value):
        """Set value by index: LList[index] = value"""
        ptr = self
        for _ in range(index):
            ptr = ptr.nxt
        ptr.value = value

    def __repr__(self):
        """Return a pretty string representation of LList"""
        return f'[{",".join([str(value) for value in self.values()])}]'

def LLNumber(value):
    """Make a LList from a number"""
    if value > 10:
        return LList(value % 10, LLNumber(value // 10))
    return LList(value)

def LLAdd(a, b):
    """Add to LList numbers"""
    carry = 0
    result = None
    for digits in itertools.zip_longest(a.values(), b.values(), fillvalue=0):
        value = sum(digits)+carry
        result = LList(value % 10, result)
        carry = value // 10
    if carry > 0:
        result = LList(carry, result)
    return result.reverse()
        
a = LLNumber(4321)
b = LLNumber(8765)
result = LLAdd(a, b)
print(a, '+', b, '=', result)
Output:
[1,2,3,4] + [5,6,7,8] = [6,8,0,3,1]
Thanks for your input. But I don't want a fancy solution. I just want to know what is wrong in my code so I can improve myself step as step. It is important for a beginner.
It would help to have the entire error message (especially including line numbers).

Your listprint() is a bit off...

     def listprint(self):
        printval = self.val
        while printval is not None:
            print (printval.val)
            printval = printval.next   
I believe self is supposed to be a node. So self.val (which you assign to printval) is an integer.

But then you ask for printval.val. That would be the same thing as self.val.val and isn't right.

I'm not sure why you're checking the val if it's None. Normally I would expect every node to have a particular value, and the .next attribute might be None (but not the val).
Let's go back to the basic design.
ListNode is presumably a node within your list. It has properties of a value and a link to the next node (linked list). This is not the whole list.
Your listprint routine, by its name, is to print the whole list. You should NOT have that as a method of an individual node. Rather, if you want to print the value of an individual node, call the method nodeprint() and just print the value.
You could then create a function at the top level that runs the list and calls nodeprint() on each linked node.
Also, when you create a new node, you should update the next of the prior linked node at that time. Using next.next is going to get you into trouble.
Look at the below. There are still issues in how I create the linked list in that it is not generalizable.
linkedlist = []
class listnode:
    def __init__(self,nvalue=0,nextnode=None,priornode=None):
        self.val = nvalue
        self.next = nextnode
        self.prior = priornode

def printlist(thelist):
    node = thelist[0]
    while node.next != None :
        print(node.val)
        node = thelist[node.next]

#build a list
node1 = listnode(2)
linkedlist.append(node1)
node1 = listnode(5,None,0)
linkedlist[0].next = 1
linkedlist.append(node1)
node1 = listnode(4,None,1)
linkedlist[1].next = 2
linkedlist.append(nodel1)
Pages: 1 2