220 likes | 348 Views
CS225: Data Structures and Software Principles Section 5. Lists. Topics . Presenting list implementations * Contiguous Singly-linked Doubly-linked Writing functions manipulating lists * Note: no iterators in these. ADT – List. Dynamic data structure Linear data structure
E N D
CS225: Data Structures and Software PrinciplesSection 5 Lists
Topics • Presenting list implementations* • Contiguous • Singly-linked • Doubly-linked • Writing functions manipulating lists *Note: no iterators in these
ADT – List • Dynamic data structure • Linear data structure • Interface is the same for all implementations • Implementation varies with the class data
Operations Creation/Destruction/Mass Update List(); List(List const & origVal); ~List(); const List& operator=(List const& origVal); void clear(); Singular Update void insertAfter(Etype const & newElem); void insertBefore(Etype const & newElem); void remove(); void update(Etype const& updateElem);
Operations Control of Current Position void front(); void back(); List& forwardOne(); List& backwardOne(); Information Access const Etype& retrieve() const; bool find(Etype const & queryElem); int length() const; void print() const;
Contiguous Implementation Data private: Array<Etype> listArray; // array that holds list of //Etype objects int current; // index of current position int numElements; // amount of space we are //using in the array e1 e2 e3 e4 e5 e6 numElements = 6 current = 0
Singly-linked Impl. Data class ListNode: Etype element; ListNode* next; private: class ListNode {…}; ListNode *head, // points to first node of list *current, // points to node at current list //position *tail; // points to last node of list int size; // number of nodes in list head current size=3 tail
Doubly-linked Impl. Data ListNode: Etype element; ListNode* next; ListNode* prev; private: // ListNode class stuff … and: ListNode *head, // points to first node of list *current, // points to node at current list position *tail; // points to last node of list int size; // number of nodes in list head current size=3 tail
void insertAfter(const Etype& newElem) • template <typename Etype> • void List<Etype>::insertAfter(Etype const & newElem) • { • typename List<Etype>::ListNode* tempNode; • tempNode = new List<Etype>::ListNode(newElem); • if (size == 0) • { • head = tempNode; • current = tempNode; • tail = tempNode; • } • else • { // standard two assignments for singly-linked list insertion • tempNode->next = current->next; • current->next = tempNode; • if (tail == current) • tail = tempNode; • current = tempNode; • } • size++; • }
void insertAfter(const Etype& newElem) • Special cases: Array: • List is full: Grow the array if needed L List: • List is empty • List is not empty, insert at tail: insert, update current, tail DL List implementation?
void remove() • See implementation.
void remove() • Special cases: • Removing from an empty list Warn user Array: (make sure you shift elements left) • Array is under-utilized e.g. size < listArray.size()/2 • Array was of size = 1 size = 0 L List: • List was size = 1 size 0: remove, all pointers NULL • Deleting last element [O(n)] • Note: Deleting head isn’t special. See regular case… DL List: • List was size = 1 like L List • Deleting last element • Deleting first element
const Etype& retrieve() const; • template <typename Etype> • Etype const & List<Etype>::retrieve() const • { • Assert(size > 0, "Cannot Retrieve an element from an empty list."); • return current->element; • }
const Etype& retrieve() const; • Special case: • Retrieving an element from an empty list Assert(size > 0, "Cannot Retrieve an element from an empty list.");
List& backwardOne(); • template <typename Etype> • void List<Etype>::backwardOne() • { • if (size > 0) // if there are nodes in the list • { • if (current != head) // and we are not at the first one • { • typename List<Etype>::ListNode* beforePtr = head; • while (beforePtr->next != current) • beforePtr = beforePtr->next; • current = beforePtr; • } • else • Warn("Cannot decrement current position when at first element."); • } • else • Warn("Cannot move to previous position of an empty list."); • }
List& backwardOne(); • Special cases: • List is empty warn user • Current == head warn user • DL implementation?
template <typename Etype>void List<Etype>::copy(List<Etype> const & origVal) • origVal - a previously allocated List object • Generally use three pointers to move through origVal, new list and create new ListNode object: • typename List<Etype>::ListNode* paramListPtr; • typename List<Etype>::ListNode* thisListPtr; • typename List<Etype>::ListNode* newestNode;
How to empty a list? • template <typename Etype> • void List<Etype>::clear() • { • typename List<Etype>::ListNode* deletionPtr = head; • current = head; • while (deletionPtr != NULL) • { • current = current->next; • delete deletionPtr; • deletionPtr = current; • } • head = NULL; • current = NULL; • tail = NULL; • size = 0; • }
Running Times • Contiguous list O(n) for insert, remove, find • Singly-linked O(1) for insertBefore, insertAfter O(n) for remove,find • Doubly-linked O(1) for insert, remove O(n) for find
Pros/Cons • Don’t waste memory( hold only as many elements) as are being currently used
Implementations • Remember special cases in all list problems • You will be working extensively with pointers so check for memory leaks • Ensure that your list remains linked throughout your operation • Write a member function of a singly linked list: swapPairs() that returns nothing, but exchanges the order of every pair of nodes in the List, excluding the last node if it has no one to swap with. You cannot create new nodes, or exchange values. You may use extra pointers as necessary. Examples: 1-2-3-4 --> 2-1-4-3 0-1-2 --> 1-0-2