1 / 30


Lists. Container Classes Many applications in Computer Science require the storage of information for collections of entities e.g. a student registration program will store records for students, a payroll system will store records for employees etc .

Download Presentation


An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.


Presentation Transcript

  1. Lists

  2. Container Classes Many applications in Computer Science require the storage of information for collections of entities e.g. a student registration program will store records for students, a payroll system will store records for employees etc. Computer Scientists have developed many techniques over the years for storing collections of data. These storage structures are known as containers. For the remainder of the course we will study some commonly used containers in Computer Science along with their implementation in an OOP language.

  3. Lists The List ADT The list is probably the simplest container type used to store collections of data. Its specification is as follows: A list L of type T is a finite sequence of elements of type T, with the following operations defined on it: • Test whether L is empty; • Determine the length of L (or the number of elements in L); • Insert an element e at position p in List L; • Find the position of an element e in List L; • Retrieve the element at position p in List L; • Delete an element e from L; • Traverse L, applying an operation to each element in L.

  4. Lists Since a list is a finite sequence of elements it makes sense to identify each element with a position in the list. This is different from a set of objects where no position is associated with each object. We will also assume that the first position in the list is identified as position 0. This follows the convention for labelling array elements in C and C++.

  5. Lists Some of the behaviours in the List ADT can be specified quite trivially. The following behaviours are more complicated to specify; • Insert • Locate • Delete • Traverse

  6. Lists insertInput: Element e,           Position p.Process:        IF (p > length() + 1)        THEN            PRINT("Error. Inserting beyond end of List")        ELSE            { Move all elements between p and the end of the list up i.e., to next position in list. }            { Make e the element at position p. }            { Increment the length. }        ENDIFOutput: None

  7. Lists Locate Input: Element eProcess:{ Note that, if the first position in the list is position 1, rather than   position 0, we would have had to initialize the index   to 1, rather than 0 } index  0 WHILE (index < length() AND element at index != e)    index <- index + 1 ENDWHILE IF (index = length())    THEN        PRINT("Error. Element did not occur in List")        RETURN –1 ELSE            RETURN index ENDIFOutput: position of e in list or –1 if e does not occur in list

  8. Lists deleteInput: Element eProcess:        pos <- locate(e)        IF (pos = -1)        THEN            { Notice that the locate has already printed an error              message. The current message is therefore not strictly              necessary )            PRINT("Error. Could not delete element")        ELSE            { Move all elements between end if list and pos + 1              to one before the position where they were }            { Decrease the size by 1 }        ENDIFOutput: None

  9. Lists traverseInput: Operation OProcess:        index <- 0        WHILE(index < length())            { Apply O to the element at index }            { Store the result at index }            index <- index + 1        ENDWHILEOutput: None

  10. Lists Most applications that maintain information about collections of entities usually require that one be able to apply a single operation to all the entities in the collection e.g. all employees in a payroll system may be given a bonus on their salary all accounts in a banking system may have interest calculated on them at the end of each month. The traverse operation is implemented to perform this function. The input to the function is an operation which is applied to all objects in the list.

  11. Lists Array-Based List Implementations Now that the List ADT has been specified there are many ways in which it can be implemented in a programming language. The easiest implementation is probably an implementation based on arrays. When we create a list we declare an array of fixed size. We can then implement the List ADT operations using array elements e.g. if we insert an element at position p, we move all the elements at position p and above up one ( assuming there is space ) and insert the new element in the free array location.

  12. Lists An empty list Some Examples Inserting numbers into the first three positions

  13. Lists Now insert 5.4 in position 1 Move elements up Insert value in position 1

  14. Lists Deleting 56.7 Locate element Remove 56.7 and shift elements down

  15. Lists List Termination How does one know where the array-based list terminates ? ( remember all array elements will contain values initially – usually garbage ) There are two possible solutions to the problem; • Use a dummy value to indicate the end of the list e.g. dummy value

  16. Lists • Keep a length attribute that stores the current length of the list. Both methods are valid means of determining the length of a list although both will generate different implementations. end=3

  17. Lists No matter what method we use there are some problems associated with array-based list implementations particularly that of overflow and wasted space. Due to the nature of arrays when implemented in a programming language we always need to specify their maximum size. Arrays cannot be dynamically created and therefore we have problems when we run out of array space and are required to add new elements – overflow. On the other hand if we declare large arrays and only use a fraction of the space then we are wasting valuable memory resources.

  18. Lists Array-based List implementation ( using dummy value for end of list ) Assume the list stores positive floating point numbers and the label DUMMY is defined as -1 to record the end of the list. The class declaration is as follows: class List  {private:    float elements[SIZE];public:    List();    Bool empty();    int length();    void insert(float, int);    int find(float);    float retrieve(int);    void del(float);    void traverse(float(*op)(float)); };

  19. Lists Thetraverse() notation void traverse(float(*op)(float)); tells the system to expect an operation *op that takes a float as an input and returns a float as output. If L is a pointer to a list and print() has been defined as a function that prints out a float and returns that number then the traverse() function can be used as follows; L->traverse(print);

  20. Lists where print() is specified as: float print(float f){    cout << f << endl;    return f;} Now that the class is declared we can specify its behaviour.

  21. Lists /* To create a list, we simply put the DUMMY element in the first position in the list. */ List::List() { elements[0] = DUMMY; } Bool List::empty() { if ( elements[0] == DUMMY ) return true; else return false; }

  22. Lists /* To determine the length of the list, we look at all elements in   the list until we either find the DUMMY element, or we reach the   end of the array of the elements making up the array */ int List::length() {    int i = 0;    while(elements[i] != DUMMY && i < SIZE)        i++;    return i; }

  23. Lists void List::insert(float e, int pos){    int i = 0;    /* First go to the end of the list */    while(elements[i] != DUMMY && i < SIZE)        i++;    /* Generate an error if there is no space left in the list */    if (i == SIZE)        cout << "Error. List is full." << endl;    else        /* Generate an error if beyond end of list */        if (pos > i)            cout << "Error. Beyond end of list." << endl;        else          

  24. Lists { /* Note that i must be pointing to the DUMMY element.               We now shift all elements between the end of the list               and the position in which the new element is to be                inserted one down. However, we must be careful not                to fall of the end of the array. If the DUMMY element               was in the last position in the array, we cannot                shift it as we would try to shift it beyond the end                of the array.  In this case we therefore first go                one position back. */            if (i == (SIZE - 1))                i--;            for(; i >= pos; i--)                elements[i + 1] = elements[i];            /* Now insert the new element */            elements[pos] = e;        }}

  25. Lists  int List::find(float e){    /* We initialize the return value ret to -1.  It only gets        changed, when we actually find the element we are looking        for.  In other words, if the element does not occur in the        list, we return position -1 */    int i = 0, ret = -1;    while(elements[i] != DUMMY && i < SIZE)    {        if (elements[i] == e)        {            ret = i;            break;           }        else i++;    }

  26. Lists if (ret == -1)        cout << "Error.  Element not in list." << endl;    return ret;}

  27. Lists float List::retrieve(int pos){    int i = 0;    /* First determine whether the position is actually a legal        position.  So, we go down the list until we either reach       the position, the DUMMY element or the end of the list */    while(elements[i] != DUMMY && i < pos && i < SIZE)        i++;    if (elements[i] == DUMMY || i == SIZE)    {        cout << "Error.  Illegal position." << endl;        return DUMMY;    }    else       return elements[pos];}

  28. Lists void List::del(float e){    int i = 0;     /* We go down the list until we find the element */    while(elements[i] != DUMMY && i < SIZE)        if (elements[i] == e)            break;        else          i++;    if (elements[i] == DUMMY || i == SIZE)        cout << "Error. Element not in list." << endl;    else

  29. Lists {        /* We move all elements one down */        while(elements[i + 1] != DUMMY && ((i + 1) < SIZE))        {           elements[i] = elements[i + 1];           i++;        }        /* Now re-insert the DUMMY */        elements[i] = DUMMY;    }}

  30. Lists void List::traverse(float (*f)(float)){    int i = 0;    while(elements[i] != DUMMY && i < SIZE)    {        elements[i] = (*f)(elements[i]);        i++;    }} Apply the operation *f to an element and store the new element in the array.

More Related