Presentation is loading. Please wait.

Presentation is loading. Please wait.

Lists. Container Classes Many applications in Computer Science require the storage of information for collections of entities e.g. a student registration.

Similar presentations


Presentation on theme: "Lists. Container Classes Many applications in Computer Science require the storage of information for collections of entities e.g. a student registration."— 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; Test whether L is empty; Determine the length of L (or the number of elements in L); Determine the length of L (or the number of elements in L); Insert an element e at position p in List L; Insert an element e at position p in List L; Find the position of an element e in List L; Find the position of an element e in List L; Retrieve the element at position p in List L; Retrieve the element at position p in List L; Delete an element e from L; Delete an element e from L; Traverse L, applying an operation to each element in 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 Insert Locate Locate Delete Delete Traverse Traverse

6 Lists insert Input: 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. } ENDIF Output: None insert Input: 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. } ENDIF Output: None

7 Lists Locate Input: Element e Process: { 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 ENDIF Output: position of e in list or –1 if e does not occur in list

8 Lists delete Input: Element e Process: 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 } ENDIF Output: None

9 Lists traverse Input: Operation O Process: index <- 0 WHILE(index < length()) { Apply O to the element at index } { Store the result at index } index <- index + 1 ENDWHILE Output: 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 Some Examples An empty list 23.656.745.2 Inserting numbers into the first three positions

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

14 Lists 23.65.456.745.2 Deleting 56.7 23.65.445.2 Remove 56.7 and shift elements down Locate element

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; 1. Use a dummy value to indicate the end of the list e.g. 23.65.456.745.20.0 dummy value

16 Lists 2. 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. 23.65.456.745.2 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 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 The traverse() notation void traverse(float(*op)(float)); 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 i) cout 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++; } 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; } 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]; } 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 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; } } { /* 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.


Download ppt "Lists. Container Classes Many applications in Computer Science require the storage of information for collections of entities e.g. a student registration."

Similar presentations


Ads by Google