2

I have written some code that contains values of players and their scores within an SLL data structure. All works fine until I try to delete a node by inputting a players ID value and then output the modified SLL without that players score.

Bellow is my class:

class PlayerScore:                          

def __init__(self, score, next = None): 
    self.length=len(score)-1
    self.rep=self.__str(score)
    self.score = score
    self.next = next

def __str(self, score):
    terms = ["(No: "+str(score[0])+ \
             ", Game1: "+str(score[1])+ \
             ", Game2: "+str(score[2]) + \
            ", Game3: "+str(score[3])]
    return str(terms)
def __eq__(self, that):
    return self.score[0] == that[0]

def delete_node(self, data):
    curr = self
    curr_score = curr.score
    prev = None;
    while curr is not None:
        if curr_score == data:
            if prev is not None:
                prev.next = curr.next
            else:
                self = curr.next
        prev = curr
        curr = self.next
    modi = curr_score
    while(modi):
        lyst = modi.marks
        total = lyst[1]+lyst[2] +lyst[3]
        print(" Student_ID.: " + str(lyst[0])+"  A1: " + str(lyst[1])+"  A2: "
            + str(lyst[2])+"  Exam: " + str(lyst[3])+" ->total " + str(total))
        modi = modi.next

Main body code:

def print_score(score_list):
if score_list is None:
    print("No player records")
    return
else:
    print("Original linked list:")
    curr = score_list
    while curr is not None:
        lyst = curr.score
        print(" PlayerNo: " + str(lyst[0])+"  Game 1: " + str(lyst[1])+"  Game 2: "
              + str(lyst[2])+"  Game 3: " + str(lyst[3]))
        curr = curr.next
    print()

def main(size = 4):

    node1 = None

    #create SLL    
    node2 = PlayerScore([199, 94, 96, 109], node1)
    node3 = PlayerScore([185, 203,  156, 171], node2)
    node4 = PlayerScore([173, 104, 190, 224], node3)
    node5 = PlayerScore([154, 268,  287, 300], node4)

    player_score_head = node5

    print_score(player_score_head)

    value = input("Enter a Student's ID for deletion: ")
    print(' ')
    player_score_head.delete_node(value)

if __name__ == "__main__":
    main() 

My question is where am I going wrong within delete_node? I do think that code is working up until to the point it has to print the new SLL but I can't workout where. Maybe I've overlooked something and just need a fresh pair of eyes to point out my silly mistake.

Just a note I am relative new to the concept of data structures and algorithms so please excuse my ignorance if I've done something the wrong way or the question does not make sense.

Thank you for the help and feedback.

2
  • 1
    Please provide a minimal reproducible example and be explicit about your input/desired output. Commented May 16, 2018 at 4:06
  • @juanpa.arrivillaga If I edit the code to show a minimal snippet then someone will state "Your code is not self contained. It cannot be run on its own and the linked list data structure is missing. How do you expect any help?". The code is complete because everything is there for it to execute up until the point the I get stuck. It's verifiable as if you'd paste it and run it in IDLE it will execute up until said point. But yes I could be more clear on my specified input/output. Commented May 16, 2018 at 5:12

1 Answer 1

1

Here's a modified version of your code with a functioning delete_node method, and I've made a few other changes to the PlayerScore class. I separated the ID number from the scores data; an ID number isn't a score, so it doesn't really make sense to combine them. I gave PlayerScore a __str__ method to make it easier to print nodes. I got rid of that __eq__ method because I found that it made the code harder to read & analyze.

I removed the modi stuff from delete_node; that stuff has nothing to do with node deletion, so it belongs in a separate method.

I've also made a couple of changes to main. I've given it an input loop so we can try deleting several nodes to test our delete_node method. And I've added a test to verify that the entered ID number can be converted to an integer.

class PlayerScore:
    def __init__(self, data, nxt=None):
        self.idnum, *self.scores = data
        self.nxt = nxt

    def __len__(self):
        return len(self.scores)

    def __str__(self):
        terms = ["No: " + str(self.idnum)]
        terms += ["Game {}: {}".format(i, v) 
            for i, v in enumerate(self.scores, 1)]
        return ', '.join(terms)

    def delete_node(self, idnum):
        curr = self
        prev = None
        # Find the node with idnum
        while curr is not None:
            if curr.idnum == idnum:
                break
            prev = curr
            curr = curr.nxt
        else:
            print("Node {} not found".format(idnum))
            return self

        #print('CURR', curr, 'PREV', prev)

        if prev is None:
            new_head = curr.nxt
        else:
            new_head = self
            prev.nxt = curr.nxt

        del curr
        return new_head

def print_score(score_list):
    if score_list is None:
        print("No player records")
        return

    print("Original linked list:")
    curr = score_list
    while curr is not None:
        print(curr)
        curr = curr.nxt
    print()

def main():
    data_list = [
        [199, 94, 96, 109],
        [185, 203,  156, 171],
        [173, 104, 190, 224],
        [154, 268,  287, 300],
    ]

    #create SLL
    head = None
    for data in data_list:
        head = PlayerScore(data, head)

    print_score(head)

    while head is not None:
        value = input("Enter a Student's ID for deletion, or 0 to exit: ")
        try:
            value = int(value)
        except ValueError:
            print("ID must be an integer")
            continue
        if value == 0:
            break
        head = head.delete_node(value)
        print_score(head)


if __name__ == "__main__":
    main()

demo output

Original linked list:
No: 154, Game 1: 268, Game 2: 287, Game 3: 300
No: 173, Game 1: 104, Game 2: 190, Game 3: 224
No: 185, Game 1: 203, Game 2: 156, Game 3: 171
No: 199, Game 1: 94, Game 2: 96, Game 3: 109

Enter a Student's ID for deletion, or 0 to exit: abc
ID must be an integer
Enter a Student's ID for deletion, or 0 to exit: 200
Node 200 not found
Original linked list:
No: 154, Game 1: 268, Game 2: 287, Game 3: 300
No: 173, Game 1: 104, Game 2: 190, Game 3: 224
No: 185, Game 1: 203, Game 2: 156, Game 3: 171
No: 199, Game 1: 94, Game 2: 96, Game 3: 109

Enter a Student's ID for deletion, or 0 to exit: 199
Original linked list:
No: 154, Game 1: 268, Game 2: 287, Game 3: 300
No: 173, Game 1: 104, Game 2: 190, Game 3: 224
No: 185, Game 1: 203, Game 2: 156, Game 3: 171

Enter a Student's ID for deletion, or 0 to exit: 154
Original linked list:
No: 173, Game 1: 104, Game 2: 190, Game 3: 224
No: 185, Game 1: 203, Game 2: 156, Game 3: 171

Enter a Student's ID for deletion, or 0 to exit: 173
Original linked list:
No: 185, Game 1: 203, Game 2: 156, Game 3: 171

Enter a Student's ID for deletion, or 0 to exit: 185
No player records
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, this a very detailed and well implemented solution to the problem I was having.
@MacGenius No worries. FWIW, we don't often use linked lists in Python (although OrderedDict uses one internally, implemented in C). A plain list (which uses a C array of pointers) is ok for many purposes, and collections.deque is great for queues and stacks. So most Python linked list code is purely an academic exercise in learning about linked lists.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.