1 / 46

Lists, Stacks, & Queues

Lists, Stacks, & Queues. Ch. 4. HW #3. Ch. 4: Exercises: 4.4, 4.6 and Project: 4.8 Due: November 3, 2009. Chapter Objectives. Learn about Lists – ADT & implementation Array based List Linked List Dictionary ADT Learn about: Queues and Stacks as restricted forms of Lists.

bsimmons
Download Presentation

Lists, Stacks, & Queues

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.

E N D

Presentation Transcript


  1. Lists, Stacks, & Queues Ch. 4

  2. HW #3 • Ch. 4: Exercises: 4.4, 4.6 and Project: 4.8 • Due: • November 3, 2009

  3. Chapter Objectives • Learn about Lists – ADT & implementation • Array based List • Linked List • Dictionary ADT • Learn about: • Queues and Stacks as restricted forms of Lists

  4. What is a List? A list is a finite, orderedsequence of data items. By ordered, we mean that each List elements has a position. Note that this is different from saying Sorted list. Notation: <a0, a1, …, an-1> Definitions: empty, length, head, tail… What operations should we implement?

  5. List Implementation Concepts The list implementation will support the concept of a current position. The list has left and right partitions separated by the fence. The fence corresponds to the current position • Either or both partitions may be empty. <20, 23 | 12, 15>

  6. Operations Examples <20, 23 | 12, 15> • Insert 10: <20, 23 | 10 12, 15> • Append 18: <20, 23 | 10 ,12, 15 18> • Remove(x): <20, 23 | 12, 15 18>, x is 10 • getvalue(x): <20, 23 | 12, 15 18>, x is 12 • next: <20, 23, 12 | 15 ,18> • Prev: <20, 23 | 12, 15, 18> • Leftlength is 2 • Rightlength is 3

  7. Operations Examples(cont) • Setstart < | 20, 23 ,12, 15 ,18> • Setend < 20, 23 12, 15 18 | > • Setpos(2) < 20, 23 | 12, 15 18 > • Setpos(4) < 20, 23 12, 15 | 18 > • Clear <|>

  8. Pure Virtual Function A pure virtual function is a function that must be overridden in a derived class and need not be defined. A virtual function is declared to be "pure" using the curious "=0" syntax. For example: class Base { public: void f1(); // not virtual virtual void f2(); // virtual, not pure virtual void f3() = 0; // pure virtual }; Base b; // error: pure virtual f3 not overridden Here, Base is an abstract class (because it has a pure virtual function), so no objects of class Base can be directly created: Base is (explicitly) meant to be a base class. For example: class Derived : public Base { // no f1: fine // no f2: fine, we inherit Base::f2 void f3(); }; Derived d; // ok: Derived::f3 overrides Base::f3 Abstract classes are immensely useful for defining interfaces. In fact, a class with only pure virtual functions is often called an interface.

  9. This ADT Defines a List interface through pure virtual functions List ADT template <class Elem> class List { public: virtual void clear() = 0; virtual bool insert(const Elem&) = 0; virtual bool append(const Elem&) = 0; virtual bool remove(Elem&) = 0; virtual void setStart() = 0; //set current position to beginning virtual void setEnd() = 0; //set current position to end virtual void prev() = 0; //move current position to previous element virtual void next() = 0; //move current position to next element virtual intleftLength() const = 0; virtual intrightLength() const = 0; virtual boolsetPos(int pos) = 0; virtual boolgetValue(Elem&) const = 0; //first element of right partition virtual void print() const = 0; };

  10. Using getValue() • Useful to tell when sequential processing is complete, e.g. For (myList.setStart(); myList.getvalue(it); myList.next()) doSomething(it);

  11. Array-Based List Insert In the average inserting or removing requires moving half the elements : (n) Print is also (n)

  12. Array-Based List Class (1) template <class Elem> // Array-based list class AList : public List<Elem> { private: int maxSize; // Maximum size of list int listSize; // Actual elem count int fence; // Position of fence Elem* listArray; // Array holding list public: AList(int size=DefaultListSize) { maxSize = size; listSize = fence = 0; listArray = new Elem[maxSize]; } // continued using C++ code

  13. Print for Array List void print() const { int temp = 0; cout << "< "; while (temp < fence) cout << listArray[temp++] << " "; cout << "| "; while (temp<listSize) cout << listArray[temp++] << " "; cout << ">\n"; }

  14. Insert for Array List template <class Elem> // Insert at front of right partition bool AList<Elem>::insert(const Elem& item) { if (listSize == maxSize) return false; // List is full for(int i=listSize; i>fence; i--) // Shift Elems up listArray[i] = listArray[i-1]; // to make room listArray[fence] = item; listSize++; // Increment list size return true; }

  15. Int Class // Your basic int type as an object. class Int { private: int val; public: Int(int input=0) { val = input; } // The following is for those times when we actually // need to get a value, rather than compare objects. int key() const { return val; } // Overload = to support Int foo = 5 syntax int operator=(int input) { val = input; } };

  16. Main Code testing AList // Driver class for list implementations // Main routine for array-based list driver class int main(int argc, char** argv) { // Declare some sample lists AList<Int*> L1; // This is a list of pointers to class Int AList<Int*> L2(15); AList<Int> L3; AList<int> L4; // This is a list of integers L1.insert(new Int(2)); //see ALIST.H for implementation of insert //see BOOK.H for implementation of Int cout << "L1: "; L1.print(); //See ALIST.H for print cin.get(); L4.insert(2); cout << "L4: "; L4.print(); cin.get(); L3.insert(2); cout << "L3: "; L3.print(); cin.get(); //recall declaration from above // template <class E1, class E2, class ListImp> // void ListTest(List<E1>& L1, List<E1>& L2, List<E2>& L3) ListTest<Int*, Int, AList<int> >(L1, L2, L3); return 0; }

  17. Linked Lists • Linked list: collection of components (nodes) • Every node (except last) has address of next node • Every node has two components (content & pointer to next) • Address of the first node of the list is stored in a separate location, called head or first

  18. Linked List Example • Linked list above has four nodes • Address of first node is stored in head • Each node has two components: • element: stores the data • Next: stores address of the next node

  19. Link (Node) Class Dynamic allocation of new list elements // Singly-linked list node template <class Elem> class Link { public: Elem element; // Value for this node Link *next; // Pointer to next node //First Constructor Link(const Elem& elemval, Link* nextval =NULL) { element = elemval; next = nextval; } //Overloaded Constructor Link(Link* nextval =NULL) { next = nextval; } };

  20. Example 1: Traversing Linked List Examples: fence=head; cout<< fence->element; fence=head->next; cout<< fence->element; Note, we can use: For (myList.setStart(); myList.getvalue(it); myList.next()) doSomething(it);

  21. Example 2: Insertion in Linked List A new node with info 50 is to be created and inserted after p: p->next=new Link(50,p->next) Equivalent to 3 steps: 1. create new_node with initial value 50, 2. make new_node->next = p-> next, 3. Change p->next = new_node

  22. Example 3: Deletion in Linked List • Suppose the node with info 34 is to be deleted from the list: q=p->next; p->next=q->next; delete q;

  23. Linked List class • For efficiency in appending, a pointer tail to the last node is used • Fence is the last node of the left partition: easier to insert and remove • Head is a first node which is not part of the useful nodes: Used for code efficiency to avoid special cases when inserting a node. • Default size is kept for application portability from AList to LList

  24. Linked List Class (1) // Linked list implementation template <class Elem> class LList: public List<Elem> { private: Link<Elem>* head; // Point to list header Link<Elem>* tail; // Pointer to last Elem Link<Elem>* fence;// Last element on left int leftcnt; // Size of left int rightcnt; // Size of right void init() { // Intialization routine fence = tail = head = new Link<Elem>; leftcnt = rightcnt = 0; } // continued using C++ code

  25. Functions to move fence void setStart() { fence = head; rightcnt += leftcnt; leftcnt = 0; } void setEnd() { fence = tail; leftcnt += rightcnt; rightcnt = 0; } void next() { if (fence != tail) // Don't move fence if right empty { fence = fence->next; rightcnt--; leftcnt++; } }

  26. Insert and Append template <class Elem> // Insert at front of right partition bool LList<Elem>::insert(const Elem& item) { fence->next = new Link<Elem>(item, fence->next); if (tail == fence) tail = fence->next; // New tail rightcnt++; return true; } template <class Elem> // Append Elem to end of the list bool LList<Elem>::append(const Elem& item) { tail = tail->next = new Link<Elem>(item, NULL); rightcnt++; return true; }

  27. Remove 1st element after fence // Remove and return first Elem in right partition template <class Elem> bool LList<Elem>::remove(Elem& it) { if (fence->next == NULL) return false; // Empty right it = fence->next->element; // Remember value Link<Elem>* ltemp = fence->next; // Remember link node fence->next = ltemp->next; // Remove from list if (tail == ltemp) tail = fence; // Reset tail delete ltemp; // Reclaim space rightcnt--; return true; }

  28. Comparison of Implementations Array-Based Lists: • Size to predetermine, space requirement is Ω(n) • Insertion and deletion are (n). • Prev and direct access are (1). • Array must be allocated in advance. • No overhead if all array positions are full. Linked Lists: • Space requirement is (n) • Insertion and deletion are (1). • Prev and direct access are (n). • Space grows with number of elements. • Every element requires overhead.

  29. Doubly Linked Lists Simplify insertion and deletion: Add aprevpointer. // Doubly-linked list link node template <class Elem> class Link { public: Elem element; // Value for this node Link *next; // Pointer to next node Link *prev; // Pointer to previous node Link(const Elem& e, Link* prevp =NULL, Link* nextp =NULL) { element=e; prev=prevp; next=nextp; } Link(Link* prevp =NULL, Link* nextp =NULL) { prev = prevp; next = nextp; } };

  30. Doubly Linked Lists

  31. Doubly Linked Insert

  32. Doubly Linked Insert // Insert at front of right partition template <class Elem> bool LList<Elem>::insert(const Elem& item) { fence->next = new Link<Elem>(item, fence, fence->next); if (fence->next->next != NULL) fence->next->next->prev = fence->next; if (tail == fence) // Appending new Elem tail = fence->next; // so set tail rightcnt++; // Added to right return true; }

  33. Doubly Linked Remove

  34. Doubly Linked Remove // Remove, return first Elem in right part template <class Elem> bool LList<Elem>::remove(Elem& it) { if (fence->next == NULL) return false; it = fence->next->element; Link<Elem>* ltemp = fence->next; if (ltemp->next != NULL) ltemp->next->prev = fence; else tail = fence; // Reset tail fence->next = ltemp->next; // Remove delete ltemp; // Reclaim space rightcnt--; // Removed from right return true; } Check code here

  35. Sorted Array List • SAList could help in speeding up search using binary search • SAList same as LIST, but redefines insert, and hides append – How?

  36. Insert & Append for SAList • Insert at location where element would fit in the right ascending order • Append can not be implemented so we hide it by having SAList get protected inheritance from Base Alist, ie: class SAList : protected List<Elem>

  37. Inherit protected from Alist Note the use of a compare class: comparing two elements / /Sorted array-based list template <class Elem, class Compare> class SAList: protected AList<Elem> { public: SAList(int size=DefaultListSize) : AList<Elem>(size) {} ~SAList() {} // Destructor AList<Elem>::clear; // Expose AList clear method // Redefine insert function to keep values sorted bool insert(const Elem& item) { // Insert at right Elem curr; for (setStart(); getValue(curr); next()) if(!Compare::lt(curr, item)) break; return AList<Elem>::insert(item); } // All remaining methods are exposed from AList AList<Elem>::remove; //…. //All other member functions of Alist are listed the same way, without exposing ‘append’ //… AList<Elem>::print; };

  38. Comparator Example class intintCompare { public: static bool lt(int x, int y) { return x < y; } static bool eq(int x, int y) { return x == y; } static bool gt(int x, int y) { return x > y; } };

  39. Comparator Example (2) Different possible ways to compare two elements (ie classes) class PayRoll { public: int ID; char* name; }; class IDCompare { public: static bool lt(Payroll& x, Payroll& y) { return x.ID < y.ID; } …. }; class NameCompare { public: static bool lt(Payroll& x, Payroll& y) { return strcmp(x.name, y.name) < 0; } ….. };

  40. Comparator Class How do we generalize comparison? • Use ==, <=, >=: Disastrous if not overloaded • Overload ==, <=, >=: may be needed for other reasons • Define a function with a standard name • Implied obligation • Breaks down with multiple key fields/indices for same object • Pass in a function/class • Explicit obligation • Template parameter

  41. Dictionary Often want to insert records, delete records, search for records. “Dictionary” is a simple interface to implement such a database Required concepts: • Search key: Describe what we are looking for. Example: How would we look for student records? • Key comparison • Equality: sequential search • Relative order: sorting • Record comparison

  42. EEComp is needed for Sorted Array list KEComp is needed when searching within dictionary Dictionary ADT // The Dictionary abstract class. template <class Key, class Elem, class KEComp, class EEComp> class Dictionary { public: virtual void clear() = 0; virtual bool insert(const Elem&) = 0; virtual bool remove(const Key&, Elem&) = 0; virtual bool removeAny(Elem&) = 0; virtual bool find(const Key&, Elem&) const = 0; virtual int size() = 0; }; Functions that need to be implemented

  43. Possible Implementations for Dictionary • Array List (Unsorted Array List) • Sort Array List • Linked List (Unsorted Linked List) • Sorted Linked List • Other custom implementations of your choice

  44. Unsorted Array List Dictionary template <class Key, class Elem, class KEComp, class EEComp> class UALdict : public //is-a Dictionary<Key,Elem,KEComp,EEComp> { private: AList<Elem>* list; //has-a public: bool remove(const Key& K, Elem& e) { for(list->setStart(); list->getValue(e); list->next()) if (KEComp::eq(K, e)) { //Comparator list->remove(e); return true; } return false; } … Implementing remove () Use KEComp class Assumes it has member functions: gt, lt, and eq

  45. Using UAL dictionary int main(int argc, char** argv) { UALdict<int, Int, intIntCompare, IntIntCompare> dict; Int val; dict.insert(10); if (dict.find(10, val)) cout << "Found value " << val << " to match key value 10\n"; else cout << "Nothing found to match key value 10\n"; ….. Instantiating a dictionary Inserting an element Finding an element with key = 10

  46. find() implementation bool find(const Key& K, Elem& e) const { for(list->setStart(); list->getValue(e); list->next()) if (KEComp::eq(K, e)) return true; return false; } Example of KEComp: class intIntCompare { public: static bool lt(int x, Int y) { return x < y.key(); } static bool eq(int x, Int y) { return x == y.key(); } static bool gt(int x, Int y) { return x > y.key(); } };

More Related