[Tutor] =Linked List Using Map

niyanaxx95 at gmail.com niyanaxx95 at gmail.com
Sun Apr 19 17:25:59 CEST 2015


Thank You Steven for your great help!!!! You really helped me to understand my assignment more as well as what maps and linked lists are.  

I used your guidance and came up with my full code. 

May you take a look and let me know what needs to be changed? Thank you in advance.



class Node:
    def __init__( self, key, value, next = None ) :
        self.key = key
        self.value = value
        self.next = next
    
    def getItem( self ) :
        return self.key
    
    def getNext( self ) :
        return self.next
    
    def setItem( self, item ) :
        self.next = next
        
    def setNext( self, next ) :
        self.next = next


class Map:
    
    def __init__( self, contents = []) :
        self.first = None
        self.last = self.first
        self.numItems = 0
        
         # traverse the linked list
        node = self.first
        while node is not None:
            print("key = %s, value = %s" % (node.key, node.value))
            node = node.next
        
        # Add new node to the end 
        node = self.first
        if node is None:
            self.first = Node("the key", "some value")
        else:
            while node.next is not None:
                node = node.next
            node.next = Node("the key", "some value")
        
            
    def length( self ) :
        if node.next == Node("the key", "some value"):
            self.numItems = self.numItems + 1
        else:
            self.numItems = self.numItems - 1
        return self.numItems
    
    def contains() :
        node = self.first
        while node is not None:
            if node.key == key:
                return True
            else:
                return False
    
    def setitem( self, key, value ) :
        node = self.first
        while node is not None:
            if key in self.key :
                        pos = self.key.index(key)
                        node.value[pos] = value
                        return
            else:
                        node = node.next          
    
    def getitem( self, key ) :
        node = self.first
        while node is not None:
            assert key in self.key
            keypos = self.key.index(key)
            return node.value[keypos]
        
    # Clears or empties the map by removing all key/value pairs
    def clear( self ):
        return self.first == None
    
    # Returns a list containing the keys stored in the map.
    def keys( self ):
        return self.key
    
    # Returns a list contain the values stored in the map.
    def values( self ):
        return self.value
    
    
    # Returns a string representation of the map in the following format:{k1:v1, k2:v2, ..., kN:vN}
    def __repr__( self ):
        return "{%s}" % (", ".join(["%s:%s" % (k,v) for k, v in zip(self._key, self._value)]))
    
    
    # Returns the minimum key in the map. The map cannot be empty.
    def min(self, key ):
        node = self.first
        while node is not None and self.first == None:
            pass
    
    # Returns the maxiumum key in the map. The map cannot be empty.
    def max( self, key ):
        node =  self.first
        while node is not None and self.first == None:
            pass
    
    # Create a new linked list that contains the same entries as the origninal
    def copy( self ):
        if self.next is None:
            return self.value
        else:
            return self.value, self.next.copy()






Sent from Windows Mail





From: Steven D'Aprano
Sent: ‎Saturday‎, ‎April‎ ‎18‎, ‎2015 ‎11‎:‎02‎ ‎PM
To: tutor at python.org
Cc: Ni'Yana Morgan





Hello Ni'Yana, and welcome!

On Fri, Apr 17, 2015 at 06:11:00PM +0000, niyanaxx95 at gmail.com wrote:

> Hello I need guidance trying to solve my assignment. I am completely 
> lost when using maps with linked lists. I understand linked lists 
> though. May someone work with me?

We will not do your homework, but perhaps we can guide you.

Thank you for showing your code. It looks like you have already made a 
lot of progress.

Unfortunately, the one thing you did not tell us is what part of the 
assignment you are having problems with! It looks like you have done 
most of the work correctly so far, so what part is giving you trouble?

A few comments on your code below:


> class Node:
>     def __init__( self, item, next = None ) :
>         self.item = item
>         self.next = next
>     def getItem( self ) :
>         return self.item
>     def getNext( self ) :
>         return self.next
>     def setItem( self, item ) :
>         self.item = item
>     def setNext( self, next ) :
>         self.next = next

Your Node class looks straightforward, but it doesn't match the 
requirements. The requirement for the Map is that it must have key:value 
pairs. But your Node doesn't have two data fields, it only has one! So 
you cannot give the Node both a key and a value.

Your Node class needs to start like this:

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


That will help get the Map class right. See my comments below.


> class Map:
>     def __init__( self, contents = []) :
>         self.first = LinkedList.Node(None, None)

First problem: you have added code which is not part of the 
specifications. The assignment says that calling Map() returns a new 
empty map. It says nothing about Map([1, 2, 3]). Get rid of the 
"contents" argument, it is not required. Once you get rid of that, the 
"for e in contents" loop is not required. Get rid of it!

Second problem: LinkedList is not defined anywhere. What is it?

The easiest way for this to work is to put the None class and the Map 
class in the same file, and then you can just say:

        self.first = Node(None, None)

without worrying about the name of the file. Java has a rule that each 
class, no matter how tiny, must go in its own file, but Python does not
have such a rule. Related classes may go in the same file.

Third problem: your assignment to self.first is wrong! That gives 
the Map a single item, not zero items!

An empty linked list will be represented here by just None alone.

        self.first = None

You then traverse the linked list like this:


    node = self.first
    while node is not None:
        print("key = %s, value = %s" % (node.key, node.value))
        node = node.next

which will print all the keys and values in the map.

To add a new node to the end, you do this:

    node = self.first
    # The empty Map case is special.
    if node is None:
        self.first = Node("the key", "some value")
    else:
        while node.next is not None:
            node = node.next
        # Now we are at the end of the linked list.
        # Add a new node.
        node.next = Node("the key", "some value")

>         self.last = self.first
>         self.numItems = 0
>         for e in contents:
>             self.append(e)
>             
>     def __len__( self ) :
>         count = 0
>         while self != None:
>             count +=1
>             self = self.next
>         return count

I don't think that this will do what your assignment asks. 

The first problem is that your assignment says that your Map must have a 
method called `length` which returns the number of items. Your Map class 
has no method called `length`, instead it uses the Python special 
__len__ method.

I think you need to change the name of this __len__ method to length. It 
is still be buggy (have you tested it?) but at least it will do what the 
assignment says.

Let us think about how to implement this length method. It is actually 
very easy! Your Map class already has a counter which tell you how many 
items are in the map, and it is initialised with:

        self.numItems = 0

so length is easy:

def length(self):
    return self.numItems


Now all you need to do is make sure that every time you add a node to 
the Map, add 1 to numItems, and every time you delete a node, you 
subtract 1.


>     def contains() :
>         pass

I assume this is just a stub which is not finished yet.

The contains method just needs to walk the linked list and look for the 
key. I showed you code above that walks the linked list printing keys 
and values. Instead of printing, you compare the node's key to the key 
you are looking for, and if they are equal, return True:

        while node is not None:
            if node.key == key:
                return True


If you reach the end of the linked list without finding the key, you 
have to return False.


Both your __setitem__ and __getitem__ methods also ignore what the 
assignment says. The assignment wants methods called `setitem` and 
`getitem`, not the special Python double-underscore methods. So you need 
to change their names, then test them.

Also, they fail to do what the assignment says. Read the requirements:

getitem(key): Returns the value associated with the given key, which 
must exist.

Does your __getitem__ method take a key as argument? No it does not, it 
takes an index!

getitem needs to take a single argument, the key. It then walks the 
linked list (as I showed you above), comparing the node's key to the 
wanted key. If they are equal, you then return node.value. If they are 
not equal, go on to the next node.

If you run out of nodes before finding the key, that is an error.

setitem needs to take two arguments, a key and a value. You then walk 
the linked list (again!) and compare the node's key to the wanted key. 
If they are equal, you set the node's value to the new value:

    node.value = value

and return.

If you run out of nodes, you add a new node at the end.

Remember what I said about incrementing the counter!

By this time, you should see a pattern. Nearly all these methods 
demonstrate the same sort of procedure: you walk the linked list, 
looking at each node in turn:

    node = self.first
    while node is not None:
        do_something_with(node)



-- 
Steve


More information about the Tutor mailing list