Today, we will extend the capabilities of the our existing linked list class. Thus far, you have simply been able to remove elements from one of the two ends of the list. Today, you will implement code that can remove an arbitrary element from the list.
To remove an element from the front of the list, you simply moved the head reference. This way, when you printed the list, you would skip over that front element. Removing an arbitrary node is very similar. Consider the following list:
Assume we wanted to remove the node containing the data "4" from said list. We simply want to make any node that "points" to that node to point around that node:
In order to accomplish this, we first need to find the node that "points" to the node who contains the data that we are trying to remove. You can simply perform a linear search through the list, until the data in the next node is the element to be removed. Finally, you can set that found nodes next reference to the node following the node being removed.
Define a method in your linked list class
called remove(self, element)
. remove
should take as a parameter the data in the node to be
removed. If element is not contained within the list, remove should
raise a ValueError
. Otherwise, you should remove the
correct node from the list, and decrement the size counter.
Make sure you thoroughly test your remove method. Can you
successfully remove the first or last elements
using remove
? What happens if you try to remove
something from an empty list? Your code should gracefully handle
all of these scenarios.
Right now, your linked list is largely complete. However, traversing the list is a bit of a pain. You create a variable called current, and continually move the current pointer to until it reaches to the end of the list. Wouldn't it be nice if you could do something more akin to this:
linked_list = LinkedList() ... for i in linked_list: print(i)
Luckily, you can. And it is not too difficult.
In order to use the above for loop syntax, your class needs to
create an iterator. An iterator is a special object that allows for
the traversal of some specified container, such as a linked list.
In Python, anything that overrides the __next__
method
are considered iterators.
The __iter__
returns some object which contains an
implementation of the __next__
method.
This __next__
continually returns the next item in the
container, until there are no more items to return. It then raises
a StopIteration
exception, which is handled internally
in python.
In your linked list class, define a private internal class
called _Iterator
. The constructor for this class
should take a reference to the linked list to iterate over, and
declare any attributes necessary to traverse the linked list. You
should define a method called __next__
within this
class. Each call to this method should return the next data from
the linked list.
Define a method in your LinkedList class
called __iter__
, which simply constructs an instance of
your private _Iterator
class, and returns it. At this
point, you should be able to iterate over the list using the above syntax.
For the purposes of this lab, you do not have to worry about some more complex issues related to iterators. One that you may run into as you use this iterator, is that if you remove items from the list, they may still exist as far as the iterator is concerned. Bonus points will be provided for any iterator implementations that solve this issue in particular.
Eratosthenes was a Greek mathematician and astronomer from the 2nd century B.C.E. He is widely known as being the one of the first humans to estimate the circumference of the Earth, with an error of less that 2%. Another contribution of Eratosthenes is the Sieve of Eratosthenes, a mechanism for computing a list of primes up to a specified number.
The algorithm for generating such a list of primes is fairly
straight forward. Consider a list of numbers numbers
in the range [2,n].
The first item in the list is always the next prime p
.
p
should be removed, and stored in the current list of
known primes. Then, every multiple of p
should be
removed from the list numbers
.
Using your LinkedList, you can implement this algorithm to get a
list of primes up to n. First, populate the numbers
list with all of the numbers from 2 until n. Also, create an empty
list called primes
. Remove the first
element, and put it in the primes
list. Then, remove all of the
multiples of n in the list numbers
. You can continue
to remove a prime and its multiples, until there are no more elements in
the numbers
list to remove.
After this algorithm is complete, the list primes
contains all of the prime numbers up to n. This list can be used to
compute the prime factorization of numbers up to n. The faster that
such a list can be generated, the faster numbers can be factored.
Time the Eratosthenes algorithm. What does its Big-O class look
like? Compare this algorithm to the old, brute-force algorithm we
discussed way back in week 1. Is this one faster?
Submit a zip file of your code on the course Inquire site that uses your last names as the file name.