Carrano - Chapter 4 CS 150 1 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.
21
Embed
Carrano - Chapter 4CS 150193 Arrays: Advantages and Disadvantages Advantages: Random access of elements is facilitated via indices. To find a[i], merely.
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Carrano - Chapter 4 CS 150 1
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.
Carrano - Chapter 4 CS 150 2
Linked Lists
Data element Location of next item
Data element NULL indicator of last element
Data element Location of next item
Data element Location of next item
Data element Location of next item
Data element Location of next item
Location of first list item
Carrano - Chapter 4 CS 150 3
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:
Carrano - Chapter 4 CS 150 4
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:
Carrano - Chapter 4 CS 150 5
A Linked List Class Definition in C++// Class definition file: linkedList.h //#ifndef LINKED_LIST_H
// 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”.
Carrano - Chapter 4 CS 150 6
The Linked List Class Implementation// Class implementation file: linkedList.cpp //#include "linkedList.h"#include <cassert>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;
Carrano - Chapter 4 CS 150 7
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.
Carrano - Chapter 4 CS 150 8
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.
Carrano - Chapter 4 CS 150 9
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.
Carrano - Chapter 4 CS 150 10
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;
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.
Carrano - Chapter 4 CS 150 11
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.
Carrano - Chapter 4 CS 150 12
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;
// 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 << ptr->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!
Carrano - Chapter 4 CS 150 13
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.
Carrano - Chapter 4 CS 150 14
A Driver to Test the Linked List Class
// Driver program to test //// the LinkedList class. //#include <iostream>#include <fstream>#include <string>#include "linkedList.h"
// 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;
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;}
Carrano - Chapter 4 CS 150 15
Test Results
Dear Contributor:
Please send money.
Please send LOTS of money.
Sincerely,Bill ClintonThe White House
Input File
Resulting Execution Window
Carrano - Chapter 4 CS 150 16
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;}
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!).
Carrano - Chapter 4 CS 150 17
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
Carrano - Chapter 4 CS 150 18
Circular Linked Lists: What Changes Are Needed?
Head
•The list is empty if The list is empty if the head points to the head points to NULL, but no active NULL, but no active node ever has a NULL node ever has a NULL next pointer.next pointer.
•To traverse the list To traverse the list just once, set up a just once, set up a “current” pointer, “current” pointer, initialized at the head; initialized at the head; when the next pointer when the next pointer of “current” is the of “current” is the head, you’re at the head, you’re at the tail.tail.
•Removing the head Removing the head item requires that its item requires that its predecessor be found predecessor be found and that the and that the predecessor’s next predecessor’s next pointer be updated.pointer be updated.
Carrano - Chapter 4 CS 150 19
Linked List Variation #2: Dummy Head Node
Rather than treating the first node as a special case, Rather than treating the first node as a special case, place a “dummy” node at the beginning of the list, and place a “dummy” node at the beginning of the list, and nevernever remove it. remove it.
•The list is empty if the dummy head node has a NULL The list is empty if the dummy head node has a NULL next pointer.next pointer.
•Removing a node merely involves changing the Removing a node merely involves changing the predecessor’s next pointer to point to the successor.predecessor’s next pointer to point to the successor.
•Inserting a node merely involves setting the new Inserting a node merely involves setting the new node’s next pointer to the predecessor’s next pointer, node’s next pointer to the predecessor’s next pointer, and setting the predecessor’s next pointer to be the and setting the predecessor’s next pointer to be the address of the new node.address of the new node.
dummy
HEAD
Carrano - Chapter 4 CS 150 20
Linked List Variation #3: Doubly Linked Lists
Every node maintains Every node maintains twotwo pointers, one to its pointers, one to its successor (the successor (the nextnext pointer) and one to its predecessor pointer) and one to its predecessor (the (the previousprevious pointer). pointer).
This eliminates the need to keep track of preceding This eliminates the need to keep track of preceding nodes during a traversal of the list.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 Removing a node requires changing the predecessor’s next pointer to point to the node’s successor next pointer to point to the node’s successor andand the the successor’s previous pointer to point to the successor’s previous pointer to point to the predecessor. Special cases involve removal of the first predecessor. Special cases involve removal of the first oror the last node. the last node.
•Inserting a node requires setting the new node’s next Inserting a node requires setting the new node’s next pointer to the successor, the new node’s previous pointer to the successor, the new node’s previous pointer to the predecessor, and both the predecessor’s pointer to the predecessor, and both the predecessor’s next pointer and the successor’s previous pointer to next pointer and the successor’s previous pointer to the address of the new node.the address of the new node.
HEAD
Carrano - Chapter 4 CS 150 21
More Advanced Linked List Variations
Top
STACKAll insertions and removals
take place from the
same end: the “top” of
the stack
RearFront
QUEUEAll insertions
occur at one end (the “rear”): all
removals occur at the other end (the “front”) Root
BINARY TREEEvery node has two pointers, pointing to