SVVRL IM NTU Lists Implementations YihKuen Tsay Dept

  • Slides: 31
Download presentation
SVVRL @ IM. NTU Lists: Implementations Yih-Kuen Tsay Dept. of Information Management National Taiwan

SVVRL @ IM. NTU Lists: Implementations Yih-Kuen Tsay Dept. of Information Management National Taiwan University Based on [Carrano and Henry 2013] With help from Chien Chin Chen 1 / 31

SVVRL @ IM. NTU Array-Based Implementation (1/2) n Tasks of ADT Implementation: 1. 2.

SVVRL @ IM. NTU Array-Based Implementation (1/2) n Tasks of ADT Implementation: 1. 2. n Choose a data structure to represent the ADT’s data. Write functions that access the data in accordance with the ADT operation specifications. Array as the data structure for lists: q Using an array to represent a list is a natural choice. n q Both an array and a list identify their items by numbers. However, an array has a fixed size, but a list can have an arbitrary length. n Yih-Kuen Tsay You need a variable to keep track of the length of the list. DS 2017: List Implementations 2 / 31

SVVRL @ IM. NTU Array-Based Implementation (2/2) n A list’s kth item is stored

SVVRL @ IM. NTU Array-Based Implementation (2/2) n A list’s kth item is stored in items[k-1]. Source: FIGURE 9 -1 in [Carrano and Henry 2013]. Yih-Kuen Tsay DS 2017: List Implementations 3 / 31

SVVRL @ IM. NTU An Array-Based List: Array. List. h (1/2) /** ADT list:

SVVRL @ IM. NTU An Array-Based List: Array. List. h (1/2) /** ADT list: Array-based implementation. @file Array. List. h */ #ifndef _ARRAY_LIST #define _ARRAY_LIST #include "List. Interface. h" #include "Precond. Violated. Excep. h" // See Stacks: Implementations template<class Item. Type> class Array. List: public List. Interface<Item. Type> { private: static const int DEFAULT_CAPACITY = 100; Item. Type items[DEFAULT_CAPACITY]; // Array of list items int item. Count; // Current count of list items int max. Items; // Maximum capacity of the list Yih-Kuen Tsay DS 2017: List Implementations 4 / 31

SVVRL @ IM. NTU An Array-Based List: Array. List. h (2/2) public: Array. List();

SVVRL @ IM. NTU An Array-Based List: Array. List. h (2/2) public: Array. List(); // Copy constructor and destructor are supplied by compiler bool is. Empty() const; int get. Length() const; bool insert(int new. Position, const Item. Type& new. Entry); bool remove(int position); void clear(); /** @throw Precond. Violated. Excep if position < 1 or position > get. Length(). */ Item. Type get. Entry(int position) const throw (Precond. Violated. Excep); /** @throw Precond. Violated. Excep if position < 1 or position > get. Length(). */ void set. Entry (int position, const Item. Type & new. Entry) throw (Precond. Violated. Excep); }; // end Array. List #include “Array. List. cpp” #endif Yih-Kuen Tsay DS 2017: List Implementations 5 / 31

SVVRL @ IM. NTU An Array-Based List: Array. List. cpp (1/7) /** @file Array.

SVVRL @ IM. NTU An Array-Based List: Array. List. cpp (1/7) /** @file Array. List. cpp */ #include “Array. List. h" // header file template<class Item. Type> Array. List<Item. Type>: : Array. List(): item. Count(0), max. Items(DEFAULT_CAPACITY) { } // end default constructor template<class Item. Type> bool Array. List<Item. Type>: : is. Empty() const { return item. Count == 0; } // end is. Empty template<class Item. Type> int Array. List<Item. Type>: : get. Length() const { return item. Count; } // end get. Length Yih-Kuen Tsay DS 2017: List Implementations 6 / 31

SVVRL @ IM. NTU An Array-Based List: Array. List. cpp (2/7) n To insert

SVVRL @ IM. NTU An Array-Based List: Array. List. cpp (2/7) n To insert an item, make room in the array. q Insertion of item 44 at position 3: k Source: FIGURE 9 -2 in [Carrano and Henry 2013]. Yih-Kuen Tsay DS 2017: List Implementations 7 / 31

SVVRL @ IM. NTU An Array-Based List: Array. List. cpp (3/7) template<class Item. Type>

SVVRL @ IM. NTU An Array-Based List: Array. List. cpp (3/7) template<class Item. Type> bool Array. List<Item. Type>: : insert(int new. Position, const Item. Type& new. Entry) { bool able. To. Insert = (new. Position >= 1) && (new. Position <= item. Count + 1) && (item. Count < max. Items); if (able. To. Insert) { // Make room for new entry by shifting all items at // positions >= new. Position toward the end of the array // (no shift if new. Position == item. Count + 1) for (int pos = item. Count; pos >= new. Position; pos--) items[pos] = items[pos-1]; // insert new. Entry items[new. Position - 1] = new. Entry; item. Count++; // Increase count of entries } // end if return able. To. Insert; } // end insert Yih-Kuen Tsay DS 2017: List Implementations 8 / 31

SVVRL @ IM. NTU An Array-Based List: Array. List. cpp (4/7) template<class Item. Type>

SVVRL @ IM. NTU An Array-Based List: Array. List. cpp (4/7) template<class Item. Type> Item. Type Array. List<Item. Type>: : get. Entry(int position) const throw (Precond. Violated. Excep) { // Enforce precondition bool able. To. Get = (position >= 1) && (position <= item. Count); if (able. To. Get) return items[position - 1]; else { string message = “get. Entry() called with an empty list or”; message = message + “invalid position. ”; throw(Precond. Violated. Excep(message)); } // end if } // end get. Entry Yih-Kuen Tsay DS 2017: List Implementations 9 / 31

SVVRL @ IM. NTU An Array-Based List: Array. List. cpp (5/7) template<class Item. Type>

SVVRL @ IM. NTU An Array-Based List: Array. List. cpp (5/7) template<class Item. Type> Item. Type Array. List<Item. Type>: : set. Entry(int position, const Item. Type& new. Entry) throw (Precond. Violated. Excep) { // Enforce precondition bool able. To. Set = (position >= 1) && (position <= item. Count); if (able. To. Set) items[position - 1] = new. Entry; else { string message = “set. Entry() called with an empty list or”; message = message + “invalid position. ”; throw(Precond. Violated. Excep(message)); } // end if } // end set. Entry Yih-Kuen Tsay DS 2017: List Implementations 10 / 31

SVVRL @ IM. NTU An Array-Based List: Array. List. cpp (6/7) n After deleting

SVVRL @ IM. NTU An Array-Based List: Array. List. cpp (6/7) n After deleting an item, fill the gap thus caused. q Removal of the entry at position 3: Fill the gap caused by the deleted item. k Source: FIGURE 9 -3 in [Carrano and Henry 2013]. Yih-Kuen Tsay DS 2017: List Implementations 11 / 31

SVVRL @ IM. NTU An Array-Based List: Array. List. cpp (7/7) template<class Item. Type>

SVVRL @ IM. NTU An Array-Based List: Array. List. cpp (7/7) template<class Item. Type> bool Array. List<Item. Type>: : remove(int position) { bool able. To. Remove = (position >= 1) && (position <= item. Count); if (able. To. Remove) { // Remove entry by shifting all entries after the one at // position toward the beginning of the array // (no shift if position == item. Count) for (int from. Index = position, to. Index = from. Index - 1; from. Index < item. Count; from. Index++, to. Index++) items[to. Index] = items[from. Index]; item. Count--; // Decrease count of entries } // end if return able. To. Remove; } // end remove Yih-Kuen Tsay DS 2017: List Implementations 12 / 31

SVVRL @ IM. NTU Link-Based Implementation (1/2) n An array has a fixed size.

SVVRL @ IM. NTU Link-Based Implementation (1/2) n An array has a fixed size. q n Using an array, data must be shifted during insertions and deletions. q n But the ADT list can have an arbitrary length. A time-consuming process. A link-based implementation avoids those problems. Yih-Kuen Tsay DS 2017: List Implementations 13 / 31

SVVRL @ IM. NTU Link-Based Implementation (2/2) n Representation of the ADT list using

SVVRL @ IM. NTU Link-Based Implementation (2/2) n Representation of the ADT list using pointers Source: FIGURE 9 -4 in [Carrano and Henry 2013]. q q q An item in the ADT list is represented as a node in the linked list. Here head. Ptr points to the first node in the linked list. In addition, the variable item. Count is the current number of entries on the list. Yih-Kuen Tsay DS 2017: List Implementations 14 / 31

SVVRL @ IM. NTU A Link-Based List: Linked. List. h (1/2) /** ADT list:

SVVRL @ IM. NTU A Link-Based List: Linked. List. h (1/2) /** ADT list: Link-based implementation. @file Linked. List. h */ #ifndef _LINKED_LIST #define _LINKED_LIST #include "List. Interface. h" #include “Node. h" // See Link-Based Implementations #include "Precond. Violated. Excep. h“ // See Stacks: Implementations template<class Item. Type> class Linked. List: public List. Interface<Item. Type> { private: Node<Item. Type>* head. Ptr; // Pointer to first node in the chain // (contains the first entry in the list) int item. Count; // Current count of list items /** Locates a specified node in a linked list. @ pre position >= 1 and position <= item. Count @ return A pointer to the node at the given position. */ Node<Item. Type>* get. Node. At(int position) const; Yih-Kuen Tsay DS 2017: List Implementations 15 / 31

SVVRL @ IM. NTU A Link-Based List: Linked. List. h (2/2) public: Linked. List();

SVVRL @ IM. NTU A Link-Based List: Linked. List. h (2/2) public: Linked. List(); Linked. List(const Linked. List<Item. Type>& a. List)); virtual ~Linked. List(); bool is. Empty() const; int get. Length() const; bool insert(int new. Position, const Item. Type& new. Entry); bool remove(int position); void clear(); /** @throw Precond. Violated. Excep if position < 1 or position > get. Length(). */ Item. Type get. Entry(int position) const throw (Precond. Violated. Excep); /** @throw Precond. Violated. Excep if position < 1 or position > get. Length(). */ void set. Entry (int position, const Item. Type & new. Entry) throw (Precond. Violated. Excep); }; // end Linked. List #include “Linked. List. cpp” #endif Yih-Kuen Tsay DS 2017: List Implementations 16 / 31

Constructor and Destructor n SVVRL @ IM. NTU The default constructor: template<class Item. Type>

Constructor and Destructor n SVVRL @ IM. NTU The default constructor: template<class Item. Type> Linked. List<Item. Type>: : Linked. List(): head. Ptr(nullptr), item. Count(0) { } // end default constructor n A destructor is required for dynamically allocated memory. template<class Item. Type> Linked. List<Item. Type>: : ~Linked. List() { Method clear invokes remove repeatedly clear(); until the list is empty, and remove deallocates } // end destructor the nodes it removes. template<class Item. Type> void Linked. List<Item. Type>: : clear() { while (!is. Empty()) remove(1); } // end clear Yih-Kuen Tsay DS 2017: List Implementations 17 / 31

The get. Entry method SVVRL @ IM. NTU template<class Item. Type> Item. Type Linked.

The get. Entry method SVVRL @ IM. NTU template<class Item. Type> Item. Type Linked. List<Item. Type>: : get. Entry(int position) const throw(Precond. Violated. Excep) { // Enforce precondition bool able. To. Get = (position >= 1) && (position <= item. Count); if (able. To. Get) { Node<Item. Type>* node. Ptr = get. Node. At(position); return node. Ptr->get. Item(); } else { string message = “get. Entry() called with an empty list or “; message = message + “invalid position”; throw (Precond. Violated. Excep(message)); } // end if } // end get. Entry Yih-Kuen Tsay DS 2017: List Implementations 18 / 31

The get. Node. At method n SVVRL @ IM. NTU Locates the node at

The get. Node. At method n SVVRL @ IM. NTU Locates the node at a given position by traversing the chain. template<class Item. Type> Node<Item. Type>* Linked. List<Item. Type>: : get. Node. At(int position) const { // Debugging check of precondition assert( (position >= 1) && (position <= item. Count) ); // Count from the beginning of the chain. Node<Item. Type>* cur. Ptr = head. Ptr; for (int skip = 1; skip < position; skip++) cur. Ptr = cur. Ptr->get. Next(); return cur. Ptr; } // end get. Node. At Yih-Kuen Tsay DS 2017: List Implementations 19 / 31

SVVRL @ IM. NTU Overview of Insertion and Deletion Insertion or deletion with pointer

SVVRL @ IM. NTU Overview of Insertion and Deletion Insertion or deletion with pointer modifications. Source: [Carrano 2007]. Yih-Kuen Tsay DS 2017: List Implementations 20 / 31

SVVRL @ IM. NTU Inserting a Node into a Specified Position (1/2) n Insert

SVVRL @ IM. NTU Inserting a Node into a Specified Position (1/2) n Insert a new node pointed to by new. Node. Ptr between the two nodes that prev. Ptr and cur. Ptr point to. 1. new. Node. Ptr->set. Next(cur. Ptr); 2. prev. Ptr->set. Next(new. Node. Ptr); . . . 20 40 2. . 100 1. 30 prev. Ptr cur. Ptr new. Node. Ptr Yih-Kuen Tsay Can we reverse the operation sequence ? YES!! DS 2017: List Implementations 21 / 31

SVVRL @ IM. NTU Inserting a Node into a Specified Position (2/2) n Inserting

SVVRL @ IM. NTU Inserting a Node into a Specified Position (2/2) n Inserting at the end of a linked list is not a special case: 1. new. Node. Ptr->set. Next(cur. Ptr); 2. prev. Ptr->set. Next(new. Node. Ptr); . . . 96 100 prev. Ptr Yih-Kuen Tsay 2. 102 new. Node. Ptr DS 2017: List Implementations 1. cur. Ptr 22 / 31

SVVRL @ IM. NTU Deleting a Specified Node (1/3) n Deleting an interior node

SVVRL @ IM. NTU Deleting a Specified Node (1/3) n Deleting an interior node N: q q Suppose that node N is pointed to by an external variable cur. Ptr. Variable prev. Ptr points to the node the precedes N. prev. Ptr->set. Next(cur. Ptr->next); Node N . . . Yih-Kuen Tsay 5 8 10 prev. Ptr cur. Ptr DS 2017: List Implementations . . . 100 23 / 31

SVVRL @ IM. NTU Deleting a Specified Node (2/3) n Deleting at the end

SVVRL @ IM. NTU Deleting a Specified Node (2/3) n Deleting at the end of a linked list is not a special case: prev. Ptr->set. Next(cur. Ptr->get. Next()); . . . Yih-Kuen Tsay 96 85 100 prev. Ptr cur. Ptr DS 2017: List Implementations 24 / 31

SVVRL @ IM. NTU Deleting a Specified Node (3/3) n n Note that node

SVVRL @ IM. NTU Deleting a Specified Node (3/3) n n Note that node N pointed to by cur. Ptr still exists after its deletion from the linked list. Return deleted node to the system. cur. Ptr->set. Next(nullptr); delete cur. Ptr; cur. Ptr = nullptr; n Three steps to delete a node: 1. 2. 3. Locate the node that you want to delete. Disconnect this node from the linked list by changing pointers. Return the node to the system. Yih-Kuen Tsay DS 2017: List Implementations 25 / 31

SVVRL @ IM. NTU Using Recursion n n Let us consider a recursive implementation

SVVRL @ IM. NTU Using Recursion n n Let us consider a recursive implementation of the insertion operation. The insert method will need a new private helper function insert. Node, which is recursive and takes three arguments: q q q position: the location (relative to the current subchain) to insert new. Node. Ptr: the new node to insert sub. Chain. Ptr: the head of the current subchain (which is some suffix portion of the original linked list) Yih-Kuen Tsay DS 2017: List Implementations 26 / 31

SVVRL @ IM. NTU Recursively Adding a Node at the Head (1/2) n The

SVVRL @ IM. NTU Recursively Adding a Node at the Head (1/2) n The current list (before the insertion): head. Ptr n 3 25 18 After method insert creates a node, before calling insert. Node (with head. Ptr for sub. Chain. Ptr): new. Node. Ptr n 12 50 As insert. Node(1, new. Node. Ptr, head. Ptr) begins execution: head. Ptr 12 3 25 18 sub. Chain. Ptr Yih-Kuen Tsay DS 2017: List Implementations 27 / 31

SVVRL @ IM. NTU Recursively Adding a Node at the Head (2/2) n After

SVVRL @ IM. NTU Recursively Adding a Node at the Head (2/2) n After the new node is linked to the beginning: head. Ptr sub. Chain. Ptr n 12 3 25 18 50 After method insert assigns to head. Ptr the returned reference: head. Ptr sub. Chain. Ptr Yih-Kuen Tsay 12 3 25 18 50 DS 2017: List Implementations 28 / 31

SVVRL @ IM. NTU Recursively Adding a Node in the Middle (1/2) n As

SVVRL @ IM. NTU Recursively Adding a Node in the Middle (1/2) n As insert. Node(3, new. Node. Ptr, head. Ptr) begins execution: head. Ptr 12 3 25 18 sub. Chain. Ptr n Recursive call insert. Node(2, new. Node. Ptr, sub. Chain. Ptr>get. Next()): head. Ptr 12 3 25 18 sub. Chain. Ptr n Recursive call insert. Node(1, new. Node. Ptr, sub. Chain. Ptr>get. Next()): head. Ptr 12 3 25 18 sub. Chain. Ptr Yih-Kuen Tsay DS 2017: List Implementations 29 / 31

SVVRL @ IM. NTU Recursively Adding a Node in the Middle (2/2) n After

SVVRL @ IM. NTU Recursively Adding a Node in the Middle (2/2) n After a new node is added to the head of subchain: head. Ptr 12 3 25 sub. Chain. Ptr n 18 50 After the returned pointer is assigned to after. Ptr: head. Ptr 12 3 25 sub. Chain. Ptr 18 50 after. Ptr n After sub. Chain. Ptr->set. Next(after. Ptr) executes: head. Ptr 12 sub. Chain. Ptr Yih-Kuen Tsay 3 25 18 50 DS 2017: List Implementations 30 / 31

Comparison and Summary n n SVVRL @ IM. NTU Reasons for choosing an array-based

Comparison and Summary n n SVVRL @ IM. NTU Reasons for choosing an array-based or a link-based implementation are similar as in the cases of Bags and Stacks. Other differences: q q An array-based list provides direct access to any of its elements, while a link-based list requires a traversal. Adding an entry to or removing an entry from an array-based list requires shifting of other entries. Inserting an item into a linked list does not shift data, an important advantage over array-based implementations. Adding or removing an entry at or near the end of a link-based list requires a time-consuming traversal. Yih-Kuen Tsay DS 2017: List Implementations 31 / 31