570 likes | 709 Views
Class 7. Objectives. Differentiate between a static data structure and a dynamic data structure Create a dynamic data structure class using a linked list Describe how nodes are inserted and remove from a linked list. What is a linked list?.
E N D
Objectives • Differentiate between a static data structure and a dynamic data structure • Create a dynamic data structure class using a linked list • Describe how nodes are inserted and remove from a linked list
What is a linked list? • It is a collection of items created dynamically (at run-time) • Each item (node) is connected through a pointer • Linked lists are differentiated from an array which is created at compile time and is accessed via a subscript • The elements in a linked list are accessed via a pointer • A linked list node consists of a data portion and at least one pointer
25 Null 3. The programmer can then place data in the data portion of the node 4. The programmer should then set nextPtr to Null or connect it to another node if there is one Data nextPtr At run-time • A node (consisting of a data portion and a pointer) is created • It’s address is placed in a pointer firstptr
Another node (consisting of a data portion and a pointer) is created • It’s address is placed in a pointer Existing node Data nextPtr 25 Null currentPtr 45 firstptr 3. The programmer can then place data in the data portion of the node
The two nodes need to be connected • Should the node with the 45 be placed before or after the node with the 25? Data nextPtr 25 Null currentPtr 45 firstptr
Placing it to the right would be processing the linked list as a queue • To the left would be a stack Data nextPtr 25 Null currentPtr 45 firstptr
To add the new node to the end of the linked list means connecting the pointer in the node with the 25 to the beginning of the node with the 45 and setting the node with the 45 pointer to Null Data nextPtr 25 Null currentPtr 45 firstptr
To add the new node to the end of the linked list means connecting the pointer in the node with the 25 to the beginning of the node with the 45 and setting the node with the 45 pointer to Null Data nextPtr 25 currentPtr 45 Null firstptr
To add the new node to the beginning of the linked list means setting the “45” node’s nextPtr to point to the “25” node and then setting firstptr the value of currentPtr so that it points to the “45” node and then Data nextPtr 25 Null currentPtr 45 firstptr
Creating a class containing a node structure and methods for processing a linked list
// Specification file for the List class #ifndef NUMBERLIST_H #define NUMBERLIST_H typedef int ListItemType; class List { private: struct ListNode { ListItemType value; struct ListNode *next; }; ListNode *head; // List head pointerint size; ListNode *find(int index) const;
public: List() // Constructor List(const List & ) { head = NULL; size =0; } ~List(); // Destructor void appendNode(ListItemType); void insert(int , const ListItemType &); void remove(int index); void retrieve(int , const ListItemType &); bool isEmpty() const; int getLength() const; }; #endif
List::List(const List& aList) : size(aList.size) { if (aList.head == NULL) head = NULL; // original list is empty else { // copy first node head = new ListNode; head->item = aList.head->item; // copy rest of list ListNode *newPtr = head; // new list pointer // newPtr points to last node in new list
// origPtr points to nodes in original list for (ListNode *origPtr = aList.head->next; origPtr != NULL; origPtr = origPtr->next) { newPtr->next = new ListNode; newPtr = newPtr->next; newPtr->item = origPtr->item; } // end for newPtr->next = NULL; } // end if } // end copy constructor
List::~List() { while (!isEmpty()) remove(1); } // end destructor bool List::isEmpty() const { return size == 0; } // end isEmpty int List::getLength() const { return size; } // end getLength
List::ListNode *List::find(int index) const { if ( (index < 1) || (index > getLength()) ) return NULL; else // count from the beginning of the list. { ListNode *cur = head; for (int skip = 1; skip < index; ++skip) cur = cur->next; return cur; } // end if } // end find
void List::retrieve(int index, ListItemType& dataItem) const { if ( (index < 1) || (index > getLength()) ) cout << "ListIndexOutOfRangeException : retrieve index out of range"); else { // get pointer to node, then data in node ListNode *cur = find(index); dataItem = cur->item; } // end if } // end
void List::insert(int index, const ListItemType& newItem) { int newLength = getLength() + 1; if ( (index < 1) || (index > newLength) ) cout << "ListIndexOutOfRangeException: insert index out of range"); else { ListNode *newPtr = new ListNode; size = newLength; newPtr->item = newItem; // attach new node to list if (index == 1) { // insert new node at beginning of list newPtr->next = head; head = newPtr; }
else { ListNode *prev = find(index-1); // insert new node after node // to which prev points newPtr->next = prev->next; prev->next = newPtr; } // end if } // end if } // end insert
void List::remove(int index) { ListNode *cur; if ( (index < 1) || (index > getLength()) ) cout << "ListIndexOutOfRangeException: remove index out of range"); else { --size; if (index == 1) { // delete the first node from the list cur = head; // save pointer to node head = head->next; }
else { ListNode *prev = find(index - 1); // delete the node after the node to which prev points cur = prev->next; // save pointer to node prev->next = cur->next; } // end if // return node to system cur->next = NULL; delete cur; cur = NULL; } // end if } // end remove
// Saves a linked list's data in a text file of // integers; head points to the linked list. // fileName is a string that names an external text // file to be created ofstream outFile(fileName); // traverse the list to the end, writing each item for (Node *cur = head; cur != NULL; cur = cur->next) outFile << cur->item << endl; outFile.close(); // Assertion: The text file contains the linked // list's data in its original order.
// Specification file for the LinkedList class #ifndef LINKEDLIST_H #define LINKEDLIST_H template <class T> class LinkedList { private: // Declare a structure for the list struct ListNode { T value; struct ListNode *next; }; ListNode *head; // List head pointer
public: LinkedList() // Constructor { head = NULL; } ~LinkedList(); // Destructor void appendNode(T); void insertNode(T); void deleteNode(T); void displayList(); }; #endif
// Implementation file for the LinkedList class #include <iostream> // For cout and NULL #include “LinkedList.h" using namespace std;template <class T> void LinkedList<T>::appendNode(T num) { ListNode *newNode, *nodePtr; // Allocate a new node & store num newNode = new ListNode; newNode->value = num; newNode->next = NULL;
// If there are no nodes in the list // make newNode the first node if (!head) head = newNode; else // Otherwise, insert newNode at end { // Initialize nodePtr to head of list nodePtr = head; // Find the last node in the list while (nodePtr->next) nodePtr = nodePtr->next; // Insert newNode as the last node nodePtr->next = newNode; } }
template <class T>void LinkedList<T>::displayList() { ListNode *nodePtr; nodePtr = head; while (nodePtr) { cout << nodePtr->value << endl; nodePtr = nodePtr->next; } }
template <class T>void LinkedList<T>::insertNode(T num) { ListNode *newNode, *nodePtr, *previousNode = NULL; // Allocate a new node & store num newNode = new ListNode; newNode->value = num; // If there are no nodes in the list // make newNode the first node if (!head) { head = newNode; newNode->next = NULL; } else
{ nodePtr = head; previousNode = NULL; while (nodePtr != NULL && nodePtr->value < num) { previousNode = nodePtr; nodePtr = nodePtr->next; } if (previousNode == NULL) { head = newNode; newNode->next = nodePtr; }
else // Otherwise, insert it after the prev. node. { previousNode->next = newNode; newNode->next = nodePtr; } } } template <class T> void LinkedList<T>::deleteNode(T num) { ListNode *nodePtr, *previousNode; // If the list is empty, do nothing. if (!head) return;
// Determine if the first node is the one. if (head->value == num) { nodePtr = head->next; delete head; head = nodePtr; } else {
// Initialize nodePtr to head of list nodePtr = head; // Skip all nodes whose value member is // not equal to num. while (nodePtr != NULL && nodePtr->value != num) { previousNode = nodePtr; nodePtr = nodePtr->next; }
// If nodePtr is not at the end of the list, // link the previous node to the node after // nodePtr, then delete nodePtr. if (nodePtr) { previousNode->next = nodePtr->next; delete nodePtr; } } }
NumberList::~NumberList() { ListNode *nodePtr, *nextNode; nodePtr = head; while (nodePtr != NULL) { nextNode = nodePtr->next; delete nodePtr; nodePtr = nextNode; } }
Creating a ListNode class instead of using a structure of type ListNode
template <class T> class List; // a forward decl. template<class T>class ListNode { friend class List< T >; // make List a friend public: ListNode( const T & ); // constructor T getData() const; // return data in the node private: T data; // data ListNode< T > *nextPtr; // next node in the list };
// Constructor template<classT> ListNode< T >::ListNode( const T &info ) : data( info ), nextPtr( 0 ) { } // Return a copy of the data in the node template< class T > T ListNode< T >::getData() const { return data; } #endif
Create a List class to do the following • Create a new node • Insert a node into the list, front and back • Delete a node from the list, front and back • Display the contents of the data portion of each node, until the end of the list
template< class T >class List {public: List(); // constructor ~List(); // destructor void insertAtFront( const T & ); void insertAtBack( const T & ); bool removeFromFront( T & ); bool removeFromBack( T & ); bool isEmpty() const; void print() const;private: ListNode< T > *firstPtr; // pointer to first node ListNode< T > *lastPtr; // pointer to last node
// PrivateUtility function to allocate a new node ListNode< T > *getNewNode( const T & ); };
// Default constructor template< class T >List< T >::List() : firstPtr( 0 ), lastPtr( 0 ) { }
// Is the List empty? template< class T > bool List< T >::isEmpty() const { return firstPtr == 0; } // Return a pointer to a newly allocated node template< class T > ListNode< T > *List< T >:: getNewNode( const T &value ) { ListNode< T > *ptr = new ListNode< T >( value ); assert( ptr != 0 ); return ptr; }
// Display the contents of the Listtemplate< class NODETYPE >void List< T >::print() const { if ( isEmpty() ) {cout << "The list is empty\n\n"; return; } ListNode< T > *currentPtr = firstPtr;cout << "The list is: "; while ( currentPtr != 0 ) { cout << currentPtr->data << ‘ ‘; currentPtr = currentPtr->nextPtr; } }
// Destructor// FOR THE WHOLE LINKED LISTtemplate< class T >List< T >::~List() { if ( !isEmpty() ) { // List is not empty cout << "Destroying nodes ...\n"; ListNode< T > *currentPtr = firstPtr, *tempPtr; while ( currentPtr != 0 ) { tempPtr = currentPtr; cout << tempPtr->data << '\n'; currentPtr = currentPtr->nextPtr; delete tempPtr; } } cout << "All nodes destroyed\n\n"; }
// Insert a node at the front of the listtemplate< class T >void List< T >::insertAtFront( const T &value ) {ListNode< T > *newPtr = getNewNode( value ); if ( isEmpty() ) // List is empty firstPtr = lastPtr = newPtr; else { // List is not empty newPtr->nextPtr = firstPtr; firstPtr = newPtr; } }
// Insert a node at the back of the listtemplate< class T > void List< T >::insertAtBack( const T &value ) { ListNode< T > *newPtr = getNewNode( value ); if ( isEmpty() ) // List is empty firstPtr = lastPtr = newPtr; else { // List is not empty lastPtr->nextPtr = newPtr; lastPtr = newPtr; }}