CMSC 341 List 2.

Slides:



Advertisements
Similar presentations
Chapter 22 Implementing lists: linked implementations.
Advertisements

DATA STRUCTURES AND ALGORITHMS Prepared by İnanç TAHRALI
Linked Lists CENG 213 Data Structures.
DATA STRUCTURES AND ALGORITHMS Lecture Notes 9 Prepared by İnanç TAHRALI.
The Template Class Chain Chain Linear list. Each element is stored in a node. Nodes are linked together using pointers.
CMSC 341 Lists 3. 2 Doubly-Linked Lists Option: add pointer to previous node Issues –doubles number of pointers –allows immediate (O(1)) access to previous.
C++ Classes and Data Structures Jeffrey S. Childs
DATA STRUCTURES AND ALGORITHMS Lecture Notes 4 Prepared by İnanç TAHRALI.
STL multimap Container. STL multimaps multimaps are associative containers –Link a key to a value –AKA: Hashtables, Associative Arrays –A multimap allows.
Nyhoff, ADTs, Data Structures and Problem Solving with C++, Second Edition, © 2005 Pearson Education, Inc. All rights reserved Stacks.
Lab05. // // // Laboratory 5 ListLinked.h // // Class declaration for the linked implementation.
ICOM 4035 – Data Structures Dr. Manuel Rodríguez Martínez Electrical and Computer Engineering Department.
M180: Data Structures & Algorithms in Java Linked Lists Arab Open University 1.
M180: Data Structures & Algorithms in Java Linked Lists – Part 2 Arab Open University 1.
Linked lists. Data structures to store a collection of items Data structures to store a collection of items are commonly used Typical operations on such.
The List ADT Reading: Sections 3.2, 3.3, 3.5.
ICOM 4035 – Data Structures Dr. Manuel Rodríguez Martínez Electrical and Computer Engineering Department.
IKI 10100I: Data Structures & Algorithms Ruli Manurung (acknowledgments to Denny & Ade Azurat) 1 Fasilkom UI Ruli Manurung (Fasilkom UI)IKI10100: Data.
IKI 10100: Data Structures & Algorithms Ruli Manurung (acknowledgments to Denny & Ade Azurat) 1 Fasilkom UI Ruli Manurung (Fasilkom UI)IKI10100: Lecture1.
CSCI  Sequence Containers – store sequences of values ◦ vector ◦ deque ◦ list  Associative Containers – use “keys” to access data rather than.
Linked Lists A formal data structure. Linked Lists Collections of data items “lined up in a row” Inserts and deletes can be done anywhere in the list.
1 Trees 3: The Binary Search Tree Reading: Sections 4.3 and 4.6.
Learning Objectives Pointers as dada members
Chapter (3) - Lists, Stacks, and Queues
Class: Special Topics Copy Constructors Static members Friends this
Lists The List ADT.
A Doubly Linked List There’s the need to access a list in reverse order prev next data dnode header 1.
Chapter 4 Linked Lists
LinkedList Class.
This pointer, Dynamic memory allocation, Constructors and Destructor
Doubly linked lists.
Chapter 16-2 Linked Structures
Trees 3: The Binary Search Tree
Linked Lists.
Chapter 4 Linked Lists.
CMSC 341 Binary Search Trees 11/19/2018.
CS 302 Data Structures Linked Lists.
CMSC 341 Hashing 12/2/2018.
CMSC 341 Binary Search Trees.
[Chapter 4; Chapter 6, pp ] CSC 143 Linked Lists [Chapter 4; Chapter 6, pp ]
CMSC 341.
CMSC 341 Binary Search Trees 1/3/2019.
Doubly Linked List Implementation
Chapter 4 Linked Lists.
CMSC 341 Hashing 2/18/2019.
CMSC 341 Lists 3.
CMSC 341 Lists 3.
CMSC 341 Binary Search Trees 2/23/2019.
CMSC 341.
Lists - I The List ADT.
Lists - I The List ADT.
CMSC 341.
CMSC 341 Binary Search Trees.
Chapter 8: Class Relationships
CMSC 341 Hashing 4/11/2019.
CMSC 341 Stacks and Queues 4/17/2019.
CMSC 341 Stacks and Queues 4/17/2019.
CMSC 341 Stacks and Queues 4/29/2019.
CMSC 341 Hashing 4/27/2019.
Lists - I The List ADT.
CMSC 341 Lecture 7.
CMSC 341 Binary Search Trees 5/8/2019.
Lists - I The List ADT.
Lists CMSC 202, Version 4/02.
CMSC 341 Binary Search Trees 5/28/2019.
Lists CMSC 202, Version 4/02.
Doubly Linked List Implementation
CMSC 341 Lecture 12.
Abstract Data Types ADT: A set of objects and a set of operations on those objects. examples: integers: +, - , *, … Collection, insert, remove, … set:
CMSC 341 Binary Search Trees 2/21/2006.
Presentation transcript:

CMSC 341 List 2

List.H template <class Object> class List { public: List(); List(const List &rhs); ~List(); const List &operator=(const List &rhs); bool isEmpty( ) const; void makeEmpty( ); void remove (const Object &x); void insert (const Object &x, const ListItr<Object> &p);

List.H (cont) ListItr<Object> first( )const; ListItr<Object> zeroth( )const; ListItr<Object> find(const Object &x) const; ListItr<Object> findPrevious(const Object &x) const; private: ListNode<Object> *header; }; Linked list implementation Use header node to avoid special cases such as insertion on empty list

ListNode.H template <class Object> class ListNode { ListNode(const Object &theElement=Object( ), ListNode *n = NULL) :element(theElement), next(n) { /* no code */ } Object element; ListNode *next; friend class List<Object>; friend class ListItr<Object>; }; Note: all fields are private. Accessible to friend classes. Constructor invoked as: ListNode() -- element will be the the object constructed by the no-argument constructor -- next will be NULL ListNode(const Object &theElement) -- element will be theElement ListNode(const Object& theElement, ListNode *n) -- element will theElement -- next will be n Note: no explicit copy constructor, assignment operator, or destructor

ListItr.H template <class Object> class ListItr { public: ListItr():current(NULL) { /* no code */ } bool isPastEnd() const {return current == NULL;} void advance( ) { if (!isPastEnd()) current = current->next; } const Object &retrieve() const { if (isPastEnd()) throw BadIterator(); return current->element; private: ListNode<Object> *current; ListItr(ListNode<Object> *theNode) :current(theNode){ /* no code */} friend class List<Object>; }; Keeps a pointer to the ListNode it considers the current one Keeps List as a friend so List can use ListItr’s private constructor The private constructor is the one used by List Why is there a public no-arg constructor? Because we want to be able to use Iterator as ordinary objects. For example, we might want to have a list of iterators over List of int List<ListItr<int>> All objects must have a zero arg constructor. For example, the ListNode used by this List of Iterators uses the no-arg constructor to intialize Note that the no-arg constructor of ListItr produces an iterator that is already exhausted (isPastEnd)

Linked List Implementation // default constructor template <class Object> List<Object>::List( ) { header = new ListNode<Object>; } bool List<Object>::isEmpty() const { return !(header->next); Constructs the empty list containing just the header node Asymptotic performance of isEmpty() =O(1) for best, worst, average

Linked List Implementation (cont) // construct an interator “pointing to” header template <class Object> ListItr<Object> List<Object>::zeroth( ) const { return ListItr<Object>(header); } // construct an iterator “pointing to” first data // element ListItr<Object> List<Object>::first( ) const { return ListItr<Object>(header->next); Uses private constructor for ListItr. It makes the iterator’s notion of current be the header node. Note: return by value. Why? Because the original in in local scope of the zeroth method. -------------------- Note: this is a valid iterator even on an empty list. It will be pastEnd

Linked List Implementation (cont) // insert at position after the one pointed // to by the iterator template <class Object> void List<Object>:: insert(const Object &x, const ListItr<Object> &p) { if (!p.isPastEnd()) //text uses p.current!=NULL p.current->next = new ListNode<Object>(x,p.current->next); } This is the only place a new ListNode is created (except for header node) If p does not belong to this list, will make a mess of some other list Asymptotic performance: O(1) best, worst, average Element of ListNode is stored as an Object, not a reference. Therefore the node stores a copy of the element passed to insert.

Linked List Implementation (cont) // return iterator pointing to item // that was found template <class Object> ListItr<Object> List<Object>:: find(const Object &x) const { ListNode<Object> *p = header->next; while (p!=NULL && p->element !=x) p = p->next; return ListItr<Object>(p); } Asymptotic performance: O(n) avg and worst O(1) best case (when x is the first element)

Linked List Implementation (cont) // return iterator to the item before // the one passed in template <class Object> ListItr<Object> List<Object>:: findPrevious( const Object &x ) const { ListNode<Object> *p = header; while (p->next!=NULL && p->next->element != x) p = p->next; return ListItr<Object>(p); } Empty List: p remains pointed at header x not on list: the while loop moves p until it points to the last node on the list. Asymptotic performance O(n): avg and worst case O(1): best case (x is first element)

Linked List Implementation (cont) // remove specified item template <class Object> void List<Object>:: remove(const Object &x) { ListItr<Object> p = findPrevious(x); if (p.current->next != NULL){ ListNode<Object> *oldnode = p.current->next; p.current->next = p.current->next->next; delete oldnode; } Early on, p could refer to 1. The header if list is empty 2. The last node if x not on list 3. The node before x, otherwise The only place where regular (non-header) nodes get deleted. Asymptotic performance: O(n): avg and worst case because of call to findPrevious O(1) in best case (x first on list)

Linked List Implementation (cont) // remove all the data, but don’t destroy // the list template <class Object> void List<Object>::makeEmpty( ) { while (!isEmpty()) remove (first().retrieve()); } Asymptotic performance: O(n) but remove is O(n) and it is called n times. How come it’s not O(n^2)? Because findPrevious,in remove, always finds the first node’s previous in O(1). So. In this case, remove (the best case) is O(1) and makeEmpty = O(n). Note -- a new first iterator is constructed in each iteration. Must do that because the previous iteration goes stale when the node is deleted. Perhaps could do: while (!isEmpty()) remove(header->next->element)

Linked List Implementation (cont) // List destructor template <class Object> List<Object>::~List() { makeEmpty(); //deletes all nodes except header delete header; } Asymptotic performance: O(n)

Linked List Implementation (cont) // assignment operator with deep copy template <class Object> const List<Object>& List<Object>:: operator= (const List<Object> &rhs) { if (this != &rhs){ makeEmpty( ); ListItr<Object> ritr = rhs.first(); ListItr<Object> itr = zeroth(); while (!ritr.isPastEnd()) { insert(ritr.retrieve(), itr); ritr.advance(); itr.advance(); } return *this; Remember: insert stores a copy of the element. Thereform, assignment is deep copy. Asymptotic performance (lhs n1, rsh n2): makeEmpty: O(n1) iteration over rhs: O(n2) = O(n1) + O(n2) = O(max(n1,n2))