Presentation is loading. Please wait.

Presentation is loading. Please wait.

Carrano - Chapter 4CS 150193 Arrays: Advantages and Disadvantages Advantages: Random access of elements is facilitated via indices.  To find a[i], merely.

Similar presentations


Presentation on theme: "Carrano - Chapter 4CS 150193 Arrays: Advantages and Disadvantages Advantages: Random access of elements is facilitated via indices.  To find a[i], merely."— Presentation transcript:

1 Carrano - Chapter 4CS 150193 Arrays: Advantages and Disadvantages Advantages: Random access of elements is facilitated via indices.  To find a[i], merely add i*(size of single element) to address of a[0].  This also facilitates sorting and searching. Enumerated list idea is easy to conceptualize. Disadvantages: A specific amount of space must be allocated.  What if the program actually requires less space?  What if the program actually requires more space? Altering the array’s contents can be time-consuming.  Inserting an element inside the array requires shifting all later array elements down to make room for it.  Removing an internal array element requires shifting all later array elements up to fill the resulting gap.

2 Carrano - Chapter 4CS 150194 Linked Lists Data elementLocation of next item Data elementNULL indicator of last element Data elementLocation of next item Data elementLocation of next item Data elementLocation of next item Data elementLocation of next item Location of first list item

3 Carrano - Chapter 4CS 150195 Linked List Advantages A variable amount of space is allocated.  No particular space requirements must be specified.  Adequate memory is provided dynamically.  Extra memory is not wasted. Altering the linked list’s contents is efficient.  Inserting an element into the linked list merely requires linking the new node to its successor and linking its predecessor to the new node. Before: After:

4 Carrano - Chapter 4CS 150196 Linked List Advantages (Continued)  Removing an element from the linked list merely requires linking the node’s predecessor to its successor. Linked List Disadvantages Random access of elements is no longer possible.  Due to the lack of indices, the entire list must be traversed when a particular element is sought. Unenumerated list idea can be difficult to conceptualize. After: Before:

5 Carrano - Chapter 4CS 150197 A Linked List Class Definition in C++ // Class definition file: linkedList.h // #ifndef LINKED_LIST_H #include using namespace std; typedef string elementType; struct node; typedef node* nodePtr; struct node { elementType item; nodePtr next; }; class LinkedList { public: // Constructors and destructor LinkedList(); LinkedList(const LinkedList &list); ~LinkedList(); // Member functions int size(); bool insert(elementType elt); bool remove(elementType elt); bool retrieve(elementType elt, int &position); elementType& operator [ ] (int position); LinkedList& operator = (const LinkedList &list); friend istream& operator >> (istream &sourceFile, LinkedList &list); friend ostream& operator << (ostream &destFile, const LinkedList &list); private: // Data member nodePtr head; // Member function nodePtr getNode(elementType elt); }; #define LINKED_LIST_H #endif Note that the mutual dependence between the definitions of the node struct and the nodePtr type requires that their definitions be handled “creatively”.

6 Carrano - Chapter 4CS 150198 The Linked List Class Implementation // Class implementation file: linkedList.cpp // #include "linkedList.h" #include using namespace std; // The default constructor merely sets up an empty LinkedList. // LinkedList::LinkedList() { head = NULL; } // The copy constructor makes a deep copy of the parameterized LinkedList. // LinkedList::LinkedList(const LinkedList &list) { nodePtr currPtr, thisCurrPtr, thisPrevPtr; if (list.head == NULL) head = NULL; else { head = getNode(list.head->item); thisPrevPtr = head; currPtr = list.head->next; while (currPtr != NULL) { thisCurrPtr = getNode(currPtr->item); thisPrevPtr->next = thisCurrPtr; thisPrevPtr = thisCurrPtr; currPtr = currPtr->next; } If list’s head is NULL, then it’s empty, so *this will also be set up that way. If list isn’t empty, repeatedly create duplicate nodes and link them into *this in the proper order. Notice the “arrow” notation; it’s equivalent to (but easier to understand than): currPtr = (*currPtr).next;

7 Carrano - Chapter 4CS 150199 The Linked List Class Implementation (Continued) // The assignment operator makes the current // object a copy of the parameterized object LinkedList& LinkedList::operator = (const LinkedList &list) { nodePtr currPtr, thisCurrPtr, thisPrevPtr; if(head == list.head) return *this; (*this).~LinkedList(); if (list.head == NULL) head = NULL; else { head = getNode(list.head->item); thisPrevPtr = head; currPtr = list.head->next; while (currPtr != NULL) { thisCurrPtr = getNode(currPtr->item); thisPrevPtr->next = thisCurrPtr; thisPrevPtr = thisCurrPtr; currPtr = currPtr->next; } return *this; } The destructor must delete every node in the old list, ensuring that no unwanted nodes remain in memory. Make sure that the user is not assigning the list to itself.

8 Carrano - Chapter 4CS 150200 The Linked List Class Implementation (Continued) // The destructor systematically deletes // // every node in the LinkedList. // LinkedList::~LinkedList() { nodePtr currPtr; while (head != NULL) { currPtr = head; head = head->next; currPtr->next = NULL; delete currPtr; } // The size member function returns the // // number of nodes in the LinkedList. // int LinkedList::size() { int count = 0; nodePtr currPtr = head; while (currPtr != NULL) { currPtr = currPtr->next; count++; } return count; } The destructor must delete every node in the list, ensuring that no dangling pointers remain. There is no data member for the size, so the nodes must be counted from scratch.

9 Carrano - Chapter 4CS 150201 The Linked List Class Implementation (Continued) // The insert member function creates a new // // node containing the parameterized value, // // inserting it at the head of the LinkedList. // // A boolean value indicating whether the // // insertion worked is returned. // bool LinkedList::insert(elementType elt) { nodePtr insertPtr = getNode(elt); if (insertPtr == NULL) return false; if (head == NULL) head = insertPtr; else { insertPtr->next = head; head = insertPtr; } return true; } If the getNode function returns a NULL pointer, then it was unable to allocate adequate memory for the new node being inserted. If the list was empty, then the new node becomes the entire list. If the list wasn’t empty, then the new node is linked in to become the new head of the list.

10 Carrano - Chapter 4CS 150202 The Linked List Class Implementation (Continued) // The remove member function locates the first occurrence of the parameterized // // value in the LinkedList and detaches it from the LinkedList. A boolean // // value indicating whether the removal worked is returned. // bool LinkedList::remove(elementType elt) { nodePtr currPtr = head; nodePtr prevPtr = NULL; bool foundIt = false; while ((!foundIt) && (currPtr != NULL)) { if (currPtr->item == elt) foundIt = true; else { prevPtr = currPtr; currPtr = currPtr->next; } if (foundIt) { if (prevPtr == NULL) head = currPtr->next; else prevPtr->next = currPtr->next; delete currPtr; } return foundIt; } Loop through the list, keeping track of the node being tested (to see if its value is elt) and its predecessor in the list. If the sought value is in the head node, then the list needs a new head. If the sought value is in a non- head node, then its predecessor must be relinked to its successor. In either case, the first node containing the sought value must be released back into the available memory heap.

11 Carrano - Chapter 4CS 150203 The Linked List Class Implementation (Continued) // The retrieve member function locates the first occurrence of the parameterized // // value in the LinkedList and sets the parameterized nodePtr to its memory // // location. A boolean value indicating whether the retrieval worked is returned. // bool LinkedList::retrieve(elementType elt, int &position) { bool foundIt = false; nodePtr currPtr = head; position = 0; while ((!foundIt) && (currPtr != NULL)) { position++; if (currPtr->item == elt) foundIt = true; else currPtr = currPtr->next; } return foundIt; } // The subscript operator retrieves the element in the parameterized position // // of the LinkedList. Note that the starting index for this operator is one. // elementType& LinkedList::operator [ ] (int position) { nodePtr currPtr = head; assert((position > 0) && (position <= size())); for (int i = 1; i < position; i++) currPtr = currPtr->next; return currPtr->item; } This retrieve function must traverse the entire list until it finds the first occurrence of the elt value. It wouldn’t be made any easier in an array implementation of the list. This retrieve function traverses the entire list until it counts off the designated number of list nodes. Because of an array’s use of consecutive memory addresses, it would be made much easier in an array implementation of the list.

12 Carrano - Chapter 4CS 150204 The Linked List Class Implementation (Continued) // The input operator reads all values of type // // elementType from the parameterized input stream, // // inserting them into the parameterized LinkedList, // // until the input stream has been completely depleted. // istream& operator >> (istream &sourceFile, LinkedList &list) { elementType nextElt; sourceFile >> nextElt; while (!sourceFile.eof()) { list.insert(nextElt); sourceFile >> nextElt; } return sourceFile; } // The output operator outputs the values in the LinkedList, // // each on a separate output line in the parameterized // // output stream, starting with the head element. // ostream& operator << (ostream &destFile, const LinkedList &list) { nodePtr ptr; for (ptr = list.head; ptr != NULL; ptr = ptr->next) destFile item << endl; return destFile; } Because the insert member function always inserts at the head of the list, the linked list will actually end up being in reverse order! Notice the use of the for loop with a pointer as our iterative variable!

13 Carrano - Chapter 4CS 150205 The Linked List Class Implementation (Continued) // The getNode member function creates and returns // // a new nodePtr, pointing to a node with the // // parameterized value as its item member and with // // NULL as the value of its next member. // nodePtr LinkedList::getNode(elementType elt) { nodePtr temp = new node; if (temp != NULL) { temp->item = elt; temp->next = NULL; } return temp; } This private member function generates a new node, loading it with the parameterized value for its item member, and a NULL pointer for its next member. It returns a pointer to the new node to the calling function.

14 Carrano - Chapter 4CS 150206 A Driver to Test the Linked List Class // Driver program to test // // the LinkedList class. // #include #include "linkedList.h" using namespace std; const string BADWORD1 = "Bill"; const string BADWORD2 = "White"; int findBadWordPosition (LinkedList list); // The main function calls // // inputs the list, and then // // searches the list for two // // "offensive" words, all // // instances of which it // // removes. // void main() { LinkedList stringList; ifstream stringFile; int position; stringFile.open("letter.txt"); stringFile >> stringList; cout << stringList << endl; position = findBadWordPosition(stringList); if (position > 0) { cout << "How dare you mention MY name: " << stringList[position] << "!!!” << endl; while ((stringList.remove(BADWORD1)) || (stringList.remove(BADWORD2))); } cout << stringList << endl; return; } // The findBadWordPosition determines the // // position of the earliest occurrence of // // BADWORD1 (if it's in the parameterized // // LinkedList) or of BADWORD2 (if it's not). // // It returns zero if neither BADWORD occurs. // int findBadWordPosition(LinkedList list) { int pos = 0; int pos1, pos2; if (list.retrieve(BADWORD1, pos1)) pos = pos1; else if (list.retrieve(BADWORD2, pos2)) pos = pos2; return pos; }

15 Carrano - Chapter 4CS 150207 Test Results Dear Contributor: Please send money. Please send LOTS of money. Sincerely, Bill Clinton The White House Input File Resulting Execution Window

16 Carrano - Chapter 4CS 150208 Modification: Outputting the List in the Original Order // The output operator outputs the values in the LinkedList, // // each on a separate output line in the parameterized // // output stream, starting with the tail element. // ostream& operator << (ostream &destFile, const LinkedList &list) { list.backwardsOutput(destFile, list.head); return destFile; } void LinkedList::backwardsOutput(ostream &outputFile, nodePtr ptr) const { if (ptr == NULL) return; else { backwardsOutput(outputFile, ptr->next); outputFile item << endl; } return; } The addition of this recursive, private member function permits the list to be output in reverse order (i.e., in the order that it was input!).

17 Carrano - Chapter 4CS 150209 Linked List Variation #1: Circular Linked Lists Head The tail node points to the head node, instead of to NULL. Traversing the list can be done “fairly”: starting with the head node and moving the head pointer as the traversal progresses. Useful approach for certain list applications, e.g., cycling through active jobs in an operating system

18 Carrano - Chapter 4CS 150210 Circular Linked Lists: What Changes Are Needed? Head The list is empty if the head points to NULL, but no active node ever has a NULL next pointer.The list is empty if the head points to NULL, but no active node ever has a NULL next pointer. To traverse the list just once, set up a “current” pointer, initialized at the head; when the next pointer of “current” is the head, you’re at the tail.To traverse the list just once, set up a “current” pointer, initialized at the head; when the next pointer of “current” is the head, you’re at the tail. Removing the head item requires that its predecessor be found and that the predecessor’s next pointer be updated.Removing the head item requires that its predecessor be found and that the predecessor’s next pointer be updated.

19 Carrano - Chapter 4CS 150211 Linked List Variation #2: Dummy Head Node Rather than treating the first node as a special case, place a “dummy” node at the beginning of the list, and never remove it. The list is empty if the dummy head node has a NULL next pointer.The list is empty if the dummy head node has a NULL next pointer. Removing a node merely involves changing the predecessor’s next pointer to point to the successor.Removing a node merely involves changing the predecessor’s next pointer to point to the successor. Inserting a node merely involves setting the new node’s next pointer to the predecessor’s next pointer, and setting the predecessor’s next pointer to be the address of the new node.Inserting a node merely involves setting the new node’s next pointer to the predecessor’s next pointer, and setting the predecessor’s next pointer to be the address of the new node. dummy HEAD

20 Carrano - Chapter 4CS 150212 Linked List Variation #3: Doubly Linked Lists Every node maintains two pointers, one to its successor (the next pointer) and one to its predecessor (the previous pointer). This eliminates the need to keep track of preceding nodes during a traversal of the list. The list is empty if the head pointer is NULL.The list is empty if the head pointer is NULL. Removing a node requires changing the predecessor’s next pointer to point to the node’s successor and the successor’s previous pointer to point to the predecessor. Special cases involve removal of the first or the last node.Removing a node requires changing the predecessor’s next pointer to point to the node’s successor and the successor’s previous pointer to point to the predecessor. Special cases involve removal of the first or the last node. Inserting a node requires setting the new node’s next pointer to the successor, the new node’s previous pointer to the predecessor, and both the predecessor’s next pointer and the successor’s previous pointer to the address of the new node.Inserting a node requires setting the new node’s next pointer to the successor, the new node’s previous pointer to the predecessor, and both the predecessor’s next pointer and the successor’s previous pointer to the address of the new node. HEAD

21 Carrano - Chapter 4CS 150213 More Advanced Linked List Variations Top STACK All insertions and removals take place from the same end: the “top” of the stack RearFront QUEUE All insertions occur at one end (the “rear”): all removals occur at the other end (the “front”) Root BINARY TREE Every node has two pointers, pointing to left and right “offspring”


Download ppt "Carrano - Chapter 4CS 150193 Arrays: Advantages and Disadvantages Advantages: Random access of elements is facilitated via indices.  To find a[i], merely."

Similar presentations


Ads by Google