Data Abstraction and Structures Using C Headington and
Data Abstraction and Structures Using C++ Headington and Riley Chapter 8 Linked Lists Slides by Sylvia Sorkin, Community College of Baltimore County - Essex 1
List l A list is a linear data structure with homogeneous components (called list items or list elements) that can only be accessed sequentially, one after the other. l We say the first item in the list is at the head or front of the list, and the last item in the list is at the tail of the list. 2
To implement the List ADT The programmer must 1) choose a concrete data representation for the list, and 2) implement the list operations. 3
How to implement a list? l Use a built-in array stored in contiguous memory locations, implementing operations by using [ ] and moving list items around in the array, as needed for insertions and deletions. l Use a linked list (to avoid excessive data movement from insertions and deletions) not necessarily stored in contiguous memory locations, but rather on the heap or free store. 4
Implementing hierarchy for a list ADT List Built-in array Linked list Built-in dynamic data and pointers Built-in array 5
A Linked List l A linked list is a collection of nodes and an external pointer to the very first node. l The nodes are structs (or class objects). l Each node contains at least one member (field) that gives the location of the next node in the list. head ‘X’ ‘C’ ‘L’ 6
Singly Linked List l In a singly linked list, each node contains only one link member. head “Ted” “Irv” “Lee” 7
Nodes can be located anywhere in memory l The link member holds the memory address of the next node in the list. 3000 head 3000 “Ted” 5000 “Irv” 4000 “Lee” NULL 8
Declarations for a Singly Linked List // Type DECLARATIONS struct Node. Type { char info; Node. Type* next; } typedef Node. Type* Node. Ptr; // Variable DECLARATIONS Node. Ptr head; ptr; ‘A’ 6000 . info . next 9
Pointer Dereferencing and Member Selection ptr ‘A’. info 6000. next *ptr (*ptr). info ptr->info ‘A’. info 6000. next 10
ptr is a pointer to a node ptr ‘A’. info 6000. next ptr 11
*ptr is the node pointed to by ptr ‘A’. info 6000. next *ptr 12
ptr->info is a node member ptr ‘A’. info 6000. next ptr->info (*ptr). info // equivalent 13
ptr->next is a node member ptr ‘A’. info 6000. next ptr->next (*ptr). next // equivalent 14
Traversing a Singly Linked List ptr 3000 head 3000 “Ted” 5000 “Irv” 4000 “Lee” NULL //PRE: head points to a singly linked list ptr = head ; while (ptr != NULL) { cout << ptr->info ; // Or, do something else with node *ptr = ptr->next ; } 15
Traversing a Singly Linked List ptr 3000 head 3000 “Ted” 5000 “Irv” 4000 “Lee” NULL //PRE: head points to a singly linked list ptr = head ; while (ptr != NULL) { cout << ptr->info ; // Or, do something else with node *ptr = ptr->next ; } 16
Traversing a Singly Linked List ptr 3000 head 3000 “Ted” 5000 “Irv” 4000 “Lee” NULL //PRE: head points to a singly linked list ptr = head ; while (ptr != NULL) { cout << ptr->info ; // Or, do something else with node *ptr = ptr->next ; } 17
Traversing a Singly Linked List ptr 3000 head 3000 “Ted” 5000 “Irv” 4000 “Lee” NULL //PRE: head points to a singly linked list ptr = head ; while (ptr != NULL) { cout << ptr->info ; // Or, do something else with node *ptr = ptr->next ; } 18
Traversing a Singly Linked List ptr 5000 3000 head 3000 “Ted” 5000 “Irv” 4000 “Lee” NULL //PRE: head points to a singly linked list ptr = head ; while (ptr != NULL) { cout << ptr->info ; // Or, do something else with node *ptr = ptr->next ; } 19
Traversing a Singly Linked List ptr 5000 3000 head 3000 “Ted” 5000 “Irv” 4000 “Lee” NULL //PRE: head points to a singly linked list ptr = head ; while (ptr != NULL) { cout << ptr->info ; // Or, do something else with node *ptr = ptr->next ; } 20
Traversing a Singly Linked List ptr 5000 3000 head 3000 “Ted” 5000 “Irv” 4000 “Lee” NULL //PRE: head points to a singly linked list ptr = head ; while (ptr != NULL) { cout << ptr->info ; // Or, do something else with node *ptr = ptr->next ; } 21
Traversing a Singly Linked List ptr 4000 3000 head 3000 “Ted” 5000 “Irv” 4000 “Lee” NULL //PRE: head points to a singly linked list ptr = head ; while (ptr != NULL) { cout << ptr->info ; // Or, do something else with node *ptr = ptr->next ; } 22
Traversing a Singly Linked List ptr 4000 3000 head 3000 “Ted” 5000 “Irv” 4000 “Lee” NULL //PRE: head points to a singly linked list ptr = head ; while (ptr != NULL) { cout << ptr->info ; // Or, do something else with node *ptr = ptr->next ; } 23
Traversing a Singly Linked List ptr 4000 3000 head 3000 “Ted” 5000 “Irv” 4000 “Lee” NULL //PRE: head points to a singly linked list ptr = head ; while (ptr != NULL) { cout << ptr->info ; // Or, do something else with node *ptr = ptr->next ; } 24
Traversing a Singly Linked List ptr NULL 3000 head 3000 “Ted” 5000 “Irv” 4000 “Lee” NULL //PRE: head points to a singly linked list ptr = head ; while (ptr != NULL) { cout << ptr->info ; // Or, do something else with node *ptr = ptr->next ; } 25
Traversing a Singly Linked List ptr NULL 3000 head 3000 “Ted” 5000 “Irv” 4000 “Lee” NULL //PRE: head points to a singly linked list ptr = head ; while (ptr != NULL) { cout << ptr->info ; // Or, do something else with node *ptr = ptr->next ; } 26
Using operator new If memory is available in an area called the free store (or heap), operator new allocates the requested object, and returns a pointer to the memory allocated. The dynamically allocated object exists until the delete operator destroys it. 27
new. Item ‘B’ Inserting a node at the front of a list char new. Item = ‘B’; Node. Type* location; location = new Node. Type; location->info = new. Item; location->next = head; head = location; head ‘X’ ‘C’ ‘L’ 28
new. Item ‘B’ Inserting a node at the front of a list char new. Item = ‘B’; Node. Type* location; location = new Node. Type; location->info = new. Item; location->next = head; head = location; head ‘X’ ‘C’ ‘L’ location 29
new. Item ‘B’ Inserting a node at the front of a list char new. Item = ‘B’; Node. Type* location; location = new Node. Type; location->info = new. Item; location->next = head; head = location; head ‘X’ ‘C’ ‘L’ location 30
new. Item ‘B’ Inserting a node at the front of a list char new. Item = ‘B’; Node. Type* location; location = new Node. Type; location->info = new. Item; location->next = head; head = location; head ‘X’ location ‘B’ ‘C’ ‘L’ 31
new. Item ‘B’ Inserting a node at the front of a list char new. Item = ‘B’; Node. Type* location; location = new Node. Type; location->info = new. Item; location->next = head; head = location; head ‘X’ location ‘B’ ‘C’ ‘L’ 32
new. Item ‘B’ Inserting a node at the front of a list char new. Item = ‘B’; Node. Type* location; location = new Node. Type; location->info = new. Item; location->next = head; head = location; head ‘X’ location ‘B’ ‘C’ ‘L’ 33
Using operator delete The object currently pointed to by the pointer is deallocated, and the pointer is considered unassigned. The memory is returned to the free store. 34
Deleting the first node from the list item Node. Type* temp. Ptr; item = head->info; temp. Ptr = head; head = head->next; delete temp. Ptr; head ‘B’ ‘X’ ‘C’ ‘L’ temp. Ptr 35
item ‘B’ Deleting the first node from the list Node. Type<Item. Type>* temp. Ptr; item = head->info; temp. Ptr = head; head = head->next; delete temp. Ptr; head ‘B’ ‘X’ ‘C’ ‘L’ temp. Ptr 36
item ‘B’ Deleting the first node from the list Node. Type<Item. Type>* temp. Ptr; item = head->info; temp. Ptr = head; head = head->next; delete temp. Ptr; head ‘B’ ‘X’ ‘C’ ‘L’ temp. Ptr 37
item ‘B’ Deleting the first node from the list Node. Type<Item. Type>* temp. Ptr; item = head->info; temp. Ptr = head; head = head->next; delete temp. Ptr; head ‘B’ ‘X’ ‘C’ ‘L’ temp. Ptr 38
item ‘B’ Deleting the first node from the list Node. Type<Item. Type>* temp. Ptr; item = head->info; temp. Ptr = head; head = head->next; delete temp. Ptr; head ‘X’ ‘C’ ‘L’ temp. Ptr 39
What is a List? l A list is a linear data structure of varying length (as items are inserted and deleted) and whose components are homogeneous with sequential access through an implicit list cursor. l Linear means each list element (except the first) has a unique predecessor, and each element (except the last) has a unique successor. 40
ADT Unsorted List Operations Transformers n Create n Insert. After n Insert. Before n Delete Observers n Is. Full n Is. Empty n End. Of. List n Current. Item Iterators Reset n Advance n change state observe state process all 41
class Person. List ~Person. List Is. Empty Current. Rec Insert. After Private data: head M a x E d 13 21 curr. Ptr Advance. . . Delete 42
// SPECIFICATION FILE person. h #include “bool. h”. . . struct Person. Rec { char* name ; int age ; }; // Pointer to person’s name // Person’s age typedef Person. Node* Node. Ptr; struct Person. Node { char* name ; int age ; Node. Ptr link ; }; // Pointer to person’s name // Person’s age // Pointer to next node in list 43
// SPECIFICATION FILE continued person. h class Person. List { public : // LINKED LIST IMPLEMENTATION Person. List ( ) ; ~Person. List ( ) ; Boolean Is. Empty ( ) const ; Boolean Is. Full ( ) const ; void Reset ( ) ; Boolean End. Of. List ( ) const ; void Insert. After ( Person. Rec some. Rec ) ; void Insert. Before ( Person. Rec some. Rec ) ; void Advance ( ); void Delete ( ) ; Person. Rec Current. Rec ( ) const ; private : Person. Node* head ; Person. Node* curr. Ptr ; }; 44
// LINKED LIST IMPLEMENTATION FILE ( person. cpp ) #include “person. h”. . . Person. List: : Person. List ( ) // constructor // PRE: None. // POST: Empty list created && End. Of. List( ). { head = NULL; curr. Ptr = NULL; } Boolean Person. List: : Is. Empty ( ) const // POST: FCTVAL == ( list is empty ) { return ( head == NULL ) ; } 45
// IMPLEMENTATION CONTINUED ( person. cpp ) void Person. List: : Reset ( ) // PRE: NOT Is. Empty ( ) // POST: List cursor is at front of list { curr. Ptr = head ; } Person. Rec Person. List: : Current. Rec ( ) const // PRE: NOT Is. Empty ( ) && NOT End. Of. List ( ) // POST: FCTVAL == record at list cursor { Person. Rec rec ; rec. name = curr. Ptr->name ; rec. age = curr. Ptr->age ; return rec ; } 46
Boolean Person. List: : End. Of. List ( ) const // POST: FCTVAL == ( list cursor is beyond end of list ) { return ( curr. Ptr == NULL ) ; } void Person. List: : Advance ( ) // PRE: NOT Is. Empty( ) && NOT End. Of. List( ) // POST: List cursor has advanced to next record { curr. Ptr = curr. Ptr->link ; } Person. List: : ~Person. List ( ) // POST: List destroyed { curr. Ptr = head ; while ( ! End. Of. List ( ) ) Delete ( ) ; } // destructor 47
void Person. List: : Insert. After ( /* in */ Person. Rec some. Rec ) // PRE: Assigned (some. Rec) && NOT Is. Empty( ) // && NOT Is. Full ( ) && NOT End. Of. List ( ) // POST: some. Rec inserted after list cursor // && This new node has become the current record { // obtain and fill a node Node. Ptr ptr = new Person. Node ; ptr->name = new char [ strlen ( some. Rec. name) + 1 ] ; strcpy( ptr->name, some. Rec. name ); ptr->age = some. Rec. age ; ptr->link = curr. Ptr->link ; curr. Ptr->link = ptr ; curr. Ptr = ptr ; } 48