C++ Classes and Data Structures Jeffrey S. Childs

Slides:



Advertisements
Similar presentations
DATA STRUCTURES USING C++ Chapter 5
Advertisements

C++ Programming: Program Design Including Data Structures, Third Edition Chapter 17: Linked Lists.
Copyright © 2008 Pearson Addison-Wesley. All rights reserved. Chapter 13 Pointers and Linked Lists.
Chapter 3: Arrays, Linked Lists, and Recursion
Data Structures Using C++ 2E
1 C++ Classes and Data Structures Jeffrey S. Childs Chapter 8 Stacks and Queues Jeffrey S. Childs Clarion University of PA © 2008, Prentice Hall.
Copyright © 2008 Pearson Addison-Wesley. All rights reserved. Chapter 13 Pointers and Linked Lists.
Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.
C++ Classes and Data Structures Jeffrey S. Childs
1 CSC 222: Computer Programming II Spring 2004 Pointers and linked lists  human chain analogy  linked lists: adding/deleting/traversing nodes  Node.
1 C++ Classes and Data Structures Jeffrey S. Childs Chapter 13 Recursion Jeffrey S. Childs Clarion University of PA © 2008, Prentice Hall.
1 C++ Classes and Data Structures Jeffrey S. Childs Chapter 14 Introduction to Sorting Algorithms Jeffrey S. Childs Clarion University of PA © 2008, Prentice.
1 C++ Classes and Data Structures Jeffrey S. Childs Chapter 5 An Array Class Jeffrey S. Childs Clarion University of PA © 2008, Prentice Hall.
1 Chapter 7 Stacks and Queues. 2 Stack ADT Recall that ADT is abstract data type, a set of data and a set of operations that act upon the data. In a stack,
Pointers OVERVIEW.
1 C++ Classes and Data Structures Jeffrey S. Childs Chapter 4 Pointers and Dynamic Arrays Jeffrey S. Childs Clarion University of PA © 2008, Prentice Hall.
Lists II. List ADT When using an array-based implementation of the List ADT we encounter two problems; 1. Overflow 2. Wasted Space These limitations are.
CMSC 341 B- Trees D. Frey with apologies to Tom Anastasio.
1 C++ Classes and Data Structures Jeffrey S. Childs Chapter 2 Overloaded Operators, Class Templates, and Abstraction Jeffrey S. Childs Clarion University.
1 Chapter 7 The Linked List as a Data Structure. 2 The List ADT A list is a list of elements. The list of elements consist of the data acted upon by list.
C++ Classes and Data Structures Jeffrey S. Childs
Dynamic Array. An Array-Based Implementation - Summary Good things:  Fast, random access of elements  Very memory efficient, very little memory is required.
Week 4 - Monday.  What did we talk about last time?  Queues  Implementing queues with circular arrays.
1 C++ Classes and Data Structures Jeffrey S. Childs Chapter 11 Hash Tables Jeffrey S. Childs Clarion University of PA © 2008, Prentice Hall.
1 C++ Classes and Data Structures Jeffrey S. Childs Chapter 15 Other Data Structures Jeffrey S. Childs Clarion University of PA © 2008, Prentice Hall.
Chapter 5 Linked List by Before you learn Linked List 3 rd level of Data Structures Intermediate Level of Understanding for C++ Please.
1 Chapter 6 Methods for Making Data Structures. 2 Dynamic Arrays in Data Structures In almost every data structure, we want functions for inserting and.
Searching CSE 103 Lecture 20 Wednesday, October 16, 2002 prepared by Doug Hogan.
MORE POINTERS Plus: Memory Allocation Heap versus Stack.
Recursion Powerful Tool
Memory Management.
Chapter 16: Linked Lists.
Recursion Version 1.0.
Linked Lists.
Lecture 6 of Computer Science II
Review Array Array Elements Accessing array elements
C++ Programming:. Program Design Including
Winter 2009 Tutorial #6 Arrays Part 2, Structures, Debugger
Pointers and Linked Lists
Pointers and Linked Lists
C++ Classes and Data Structures Jeffrey S. Childs
Review Deleting an Element from a Linked List Deletion involves:
Data Structure and Algorithms
Lecture - 6 On Data Structures
Linked lists.
Queues Queues Queues.
Linked Lists head One downside of arrays is that they have a fixed size. To solve this problem of fixed size, we’ll relax the constraint that the.
Prof. Neary Adapted from slides by Dr. Katherine Gibson
Introduction to Linked Lists
CMSC 341 Lecture 10 B-Trees Based on slides from Dr. Katherine Gibson.
Circular Buffers, Linked Lists
Optimizing Malloc and Free
C++ Classes and Data Structures Jeffrey S. Childs
Arrays and Linked Lists
Chapter 15 Pointers, Dynamic Data, and Reference Types
Pointers and Linked Lists
B- Trees D. Frey with apologies to Tom Anastasio
Linked Lists.
B- Trees D. Frey with apologies to Tom Anastasio
A Robust Data Structure
Linked List.
B- Trees D. Frey with apologies to Tom Anastasio
Basics of Recursion Programming with Recursion
Advanced Implementation of Tables
CENG 218 Classes and Data Structures
Lists.
slides created by Ethan Apter
Linked lists.
Classes and Objects Object Creation
Presented by : Aman Gupta PGT CS KV No.1, Narimedu, Madurai
Presentation transcript:

C++ Classes and Data Structures Jeffrey S. Childs Chapter 7 Methods for Making Data Structures Jeffrey S. Childs Clarion University of PA © 2008, Prentice Hall

Dynamic Arrays in Data Structures In the class for a data structure, we can add an Array object to the private section to store data The functions of the data structure can expand or shrink the Array to conserve memory – this relieves the client from thinking about doing this

Dynamic Arrays in Data Structures (cont.) In almost every data structure, we want functions for inserting and removing data When dynamic arrays are used, the insertion function would add data to the array, while the removal function would “eliminate” data from the array (make it unusable) When the array becomes full, we would want to do an expansion – when many elements have been removed, we would want to do a contraction, so that only the used elements remain

Array Expansion/Contraction One possible method: When an element is inserted by the client, increase the size of the array by 1 When an element is removed by the client, decrease the size of the array by 1 The problem with this method is that it is inefficient – every time an element is inserted or removed, the changeSize function is called…

changeSize Function 33 0 1 2 3 432 433 444 445 … 25 75 10 12 56 32 73 87 New element needs to be put into array, so changeSize function is called

changeSize Function (cont.) 0 1 2 3 432 433 444 445 … 25 75 10 12 56 32 73 87 0 1 2 3 432 433 444 445 446 … new array is made

changeSize Function (cont.) 0 1 2 3 432 433 444 445 … 25 75 10 12 56 32 73 87 0 1 2 3 432 433 444 445 446 … 25 75 10 12 56 32 73 87 elements are copied over one by one using a for loop

changeSize Function (cont.) 33 0 1 2 3 432 433 444 445 446 … 25 75 10 12 56 32 73 87 33 Then, the new element can be put in

changeSize Function (cont.) 0 1 2 3 432 433 444 445 446 … 25 75 10 12 56 32 73 87 33 This process would take place every time a new element needs to be inserted.

changeSize Function (cont.) 0 1 2 3 432 433 444 445 446 … 25 75 10 12 56 32 73 87 33 Likewise, when an element needs to be removed, this method contracts the array by one to conserve memory.

changeSize Function (cont.) 0 1 2 3 432 433 444 445 446 … 25 75 10 12 56 32 73 87 33 Suppose the element at the end of the array needs to be removed.

changeSize Function (cont.) 0 1 2 3 432 433 444 445 446 … 25 75 10 12 56 32 73 87 33 0 1 2 3 432 433 444 445 … The changeSize function is called and a new, smaller array is made.

changeSize Function (cont.) 0 1 2 3 432 433 444 445 446 … 25 75 10 12 56 32 73 87 33 0 1 2 3 432 433 444 445 … 25 75 10 12 56 32 73 87 The elements are copied over one by one, using a for loop.

changeSize Function (cont.) 0 1 2 3 432 433 444 445 … 25 75 10 12 56 32 73 87 This method of array expansion/contraction is largely inefficient, because there is too much element copying.

A Better Method When the Array is full, double the size of it When the number of elements used in the Array falls to 25% of the Array’s capacity, cut the size of the Array in half (it will be half full after the cut)

A Better Method (cont.) 0 1 2 3 25 75

A Better Method (cont.) 0 1 2 3 25 75 10

A Better Method (cont.) 0 1 2 3 25 75 10 12

A Better Method (cont.) 0 1 2 3 33 25 75 10 12 Array is full, so call changeSize function to double the size.

A Better Method (cont.) 0 1 2 3 4 5 6 7 25 75 10 12 33

A Better Method (cont.) 0 1 2 3 4 5 6 7 25 75 10 12 33 49 29 87 This array is full, but if we removed elements (made them inaccessible), we would cut the size of the array in half when its utilization drops to 25%

A Better Method (cont.) 0 1 2 3 4 5 6 7 25 75 10 12 33 49 29

A Better Method (cont.) 0 1 2 3 4 5 6 7 25 75 10 12 33 49

A Better Method (cont.) 0 1 2 3 4 5 6 7 25 75 10 12 33

A Better Method (cont.) 0 1 2 3 4 5 6 7 25 75 10 12

A Better Method (cont.) 0 1 2 3 4 5 6 7 25 75 10

A Better Method (cont.) 0 1 2 3 4 5 6 7 25 75 Array is 25% utilized, so use changeSize function to cut the size of the array in half.

A Better Method (cont.) 0 1 2 3 25 75 Array is 25% utilized, so use changeSize function to cut the size of the array in half.

A Better Method (cont.) 0 1 2 3 25 75 Using this method, memory is still conserved. There is element copying every time changeSize is called, but it isn’t bad.

A Better Method (cont.) 0 1 2 3 25 75 It can be proven that, on average, there are no more than a couple of elements being copied on each insertion/deletion with this method.

Linked Structures In a data structure, data is not always stored in an Array object Sometimes it is best to store data in a linked structure (an alternative to an Array) A linked structure consists of a group of nodes – each node is made from a struct. An object of the Node struct contains an element of data.

A Node Struct Template template <class DataType> struct Node { DataType info; Node<DataType> *next; }; The info member is for the data. It can anything (DataType), but it is often the object of another struct, used as a record of information.

A Node Struct Template (cont.) template <class DataType> struct Node { DataType info; Node<DataType> *next; }; The next pointer stores the address of a Node of the same type! This means that each node can point to another node.

Nodes In a data structure, each node is made in the heap; therefore, a node can only be accessed by a pointer. The client does not deal with nodes. When the client uses an insertion function, an element of data is passed into the function, and the function places it in a node.

Nodes (cont.) When the client wants to retrieve data, the data in a node is returned to the client (but not the node itself). The node struct template exists for use by the data structure.

Example of a Linked Structure start Each blue node is divided into two sections, for the two members of the Node struct.

Example of a Linked Structure (cont.) start The left section is the info member.

Example of a Linked Structure (cont.) start The right section is the pointer called “next”.

Example of a Linked Structure (cont.) start The start pointer would be saved in the private section of a data structure class.

Example of a Linked Structure (cont.) start The last node doesn’t point to another node, so its pointer (called next) is set to NULL (indicated by slash).

Linked Lists The arrangement of nodes in the linked structure on the previous slide is often called a linked list. We can access any element of the linked list, for retrieval of information. We can also remove any element from the linked list (which would shorten the list). We can also insert any element into any position in the linked list.

Linked List Advantages … … 5 3 7 2 1 Removing an element from the middle of a linked list is fast.

Linked List Advantages (cont.) … … 5 3 2 1 Removing an element from the middle of a linked list is fast.

Linked List Advantages (cont.) 211 212 213 214 215 216 217 218 … … 25 75 10 12 33 49 29 87 Removing elements from the middle of an array (without leaving gaps) is more problematic.

Linked List Advantages (cont.) 211 212 213 214 215 216 217 218 … … 25 75 10 33 49 29 87 Removing elements from the middle of an array (without leaving gaps) is more problematic.

Linked List Advantages (cont.) 211 212 213 214 215 216 217 218 … … 25 75 10 33 49 29 87 A loop must be used to slide each element on the right one slot to the left, one at a time…

Linked List Advantages (cont.) 211 212 213 214 215 216 217 218 … … 25 75 10 33 49 29 87

Linked List Advantages (cont.) 211 212 213 214 215 216 217 218 … … 25 75 10 33 49 29 87

Linked List Advantages (cont.) 211 212 213 214 215 216 217 218 … … 25 75 10 33 49 29 87

Linked List Advantages (cont.) 211 212 213 214 215 216 217 218 … … 25 75 10 33 49 29 87

Linked List Advantages (cont.) 211 212 213 214 215 216 217 218 … … 25 75 10 33 49 29 87 Only 100,000 more to go!

Linked List Advantages (cont.) Linked lists also waste less memory for large elements (records of information). Wasted memory is memory space in the data structure not used for data. In arrays, the wasted memory is the part of the array not being utilized. In linked lists, the wasted memory is the pointer in each node.

Linked List Advantages (cont.) start Linked List Array

Accessing info start To access the info in the first node: (*start).info

Accessing info (cont.) start To access the info in the first node: (*start).info Or (better yet) start->info dereference and member access in one shot

Accessing info (cont.) start To access the info in the second node: start->next->info

Finding the Mercedes start … Mercedes Consider a linked list, where the info member (left half of blue box) is a CarType object We wish to find a Mercedes stored in one of the objects.

Finding the Mercedes (cont.) start … Mercedes CarType item; item.maker = “Mercedes”; Node<CarType> *ptr = start; while ( ptr->info != item ) // overloaded operator ptr = ptr->next;

Finding the Mercedes (cont.) start … Mercedes CarType item; item.maker = “Mercedes”; Node<CarType> *ptr = start; while ( ptr->info != item ) // overloaded operator ptr = ptr->next;

Finding the Mercedes (cont.) start item maker: price: year: operator != … Mercedes CarType item; item.maker = “Mercedes”; Node<CarType> *ptr = start; while ( ptr->info != item ) // overloaded operator ptr = ptr->next;

Finding the Mercedes (cont.) start item maker: price: year: operator != … Mercedes CarType item; item.maker = “Mercedes”; Node<CarType> *ptr = start; while ( ptr->info != item ) // overloaded operator ptr = ptr->next;

Finding the Mercedes (cont.) start item maker: Mercedes price: year: operator != … Mercedes CarType item; item.maker = “Mercedes”; Node<CarType> *ptr = start; while ( ptr->info != item ) // overloaded operator ptr = ptr->next;

Finding the Mercedes (cont.) start item maker: Mercedes price: year: operator != … Mercedes CarType item; item.maker = “Mercedes”; Node<CarType> *ptr = start; while ( ptr->info != item ) // overloaded operator ptr = ptr->next;

Finding the Mercedes (cont.) start ptr item maker: Mercedes price: year: operator != … Mercedes CarType item; item.maker = “Mercedes”; Node<CarType> *ptr = start; while ( ptr->info != item ) // overloaded operator ptr = ptr->next;

Finding the Mercedes (cont.) start ptr item maker: Mercedes price: year: operator != … Mercedes CarType item; item.maker = “Mercedes”; Node<CarType> *ptr = start; while ( ptr->info != item ) // overloaded operator ptr = ptr->next;

Finding the Mercedes (cont.) start ptr item maker: Mercedes price: year: operator != … Mercedes CarType item; item.maker = “Mercedes”; Node<CarType> *ptr = start; while ( ptr->info != item ) // overloaded operator ptr = ptr->next;

Finding the Mercedes (cont.) start ptr item maker: Mercedes price: year: operator != … Mercedes CarType item; item.maker = “Mercedes”; Node<CarType> *ptr = start; while ( ptr->info != item ) // overloaded operator ptr = ptr->next;

Finding the Mercedes (cont.) start ptr item maker: Mercedes price: year: operator != … Mercedes Loop repeats, ptr moves through list CarType item; item.maker = “Mercedes”; Node<CarType> *ptr = start; while ( ptr->info != item ) // overloaded operator ptr = ptr->next;

Finding the Mercedes (cont.) start ptr item maker: Mercedes price: year: operator != … Mercedes CarType item; item.maker = “Mercedes”; Node<CarType> *ptr = start; while ( ptr->info != item ) // overloaded operator ptr = ptr->next;

Finding the Mercedes (cont.) start ptr item maker: Mercedes price: year: operator != … Mercedes CarType item; item.maker = “Mercedes”; Node<CarType> *ptr = start; while ( ptr->info != item ) // overloaded operator ptr = ptr->next; FOUND!

Finding the Mercedes (cont.) start ptr item maker: Mercedes price: year: operator != … Mercedes Loop stops ptr points to the node containing Mercedes Can return ptr->info to the client, so that the client can access data members, such as price

What if no Mercedes? The code we looked at assumes there is a Mercedes in the linked list The following slides show the error that will occur if Mercedes is not in the linked list…

No Mercedes item start ptr maker: Mercedes price: year: operator != … CarType item; item.maker = “Mercedes”; Node<CarType> *ptr = start; while ( ptr->info != item ) // overloaded operator ptr = ptr->next;

No Mercedes (cont.) item start ptr maker: Mercedes price: year: operator != … CarType item; item.maker = “Mercedes”; Node<CarType> *ptr = start; while ( ptr->info != item ) // overloaded operator ptr = ptr->next;

No Mercedes (cont.) item start ptr maker: Mercedes price: year: operator != … CarType item; item.maker = “Mercedes”; Node<CarType> *ptr = start; while ( ptr->info != item ) // overloaded operator ptr = ptr->next;

No Mercedes (cont.) item start ptr maker: Mercedes price: year: operator != … CarType item; item.maker = “Mercedes”; Node<CarType> *ptr = start; while ( ptr->info != item ) // overloaded operator ptr = ptr->next;

No Mercedes (cont.) item start ptr maker: Mercedes price: year: operator != … CarType item; item.maker = “Mercedes”; Node<CarType> *ptr = start; while ( ptr->info != item ) // overloaded operator ptr = ptr->next;

No Mercedes (cont.) item start ptr is set to NULL maker: Mercedes price: year: operator != … CarType item; item.maker = “Mercedes”; Node<CarType> *ptr = start; while ( ptr->info != item ) // overloaded operator ptr = ptr->next;

No Mercedes (cont.) item start ptr is set to NULL maker: Mercedes price: year: operator != … CarType item; item.maker = “Mercedes”; Node<CarType> *ptr = start; while ( ptr->info != item ) // overloaded operator ptr = ptr->next;

No Mercedes (cont.) item start ptr is set to NULL maker: Mercedes price: year: operator != … CarType item; item.maker = “Mercedes”; Node<CarType> *ptr = start; while ( ptr->info != item ) ptr = ptr->next; Runtime error!

Finding a Possible Mercedes start item maker: Mercedes price: year: operator == … Let’s solve the problem, but let’s assume that item is passed in as a parameter (of type DataType). This is normally what would happen. Instead of the CarType struct having an overloaded != operator, it will have an overloaded == operator.

Finding a Possible Mercedes (cont.) start item maker: Mercedes price: year: operator == … Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) // overloaded == found = true; if ( !found ) ptr = ptr->next; }

Finding a Possible Mercedes (cont.) start item maker: Mercedes price: year: operator == … Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) // overloaded == found = true; if ( !found ) ptr = ptr->next; }

Finding a Possible Mercedes (cont.) start ptr item maker: Mercedes price: year: operator == … Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) // overloaded == found = true; if ( !found ) ptr = ptr->next; }

Finding a Possible Mercedes (cont.) start ptr item maker: Mercedes price: year: operator == … Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) // overloaded == found = true; if ( !found ) ptr = ptr->next; }

Finding a Possible Mercedes (cont.) start ptr item maker: Mercedes price: year: operator == … Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) // overloaded == found = true; if ( !found ) ptr = ptr->next; } found: false

Finding a Possible Mercedes (cont.) start ptr item maker: Mercedes price: year: operator == … Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) // overloaded == found = true; if ( !found ) ptr = ptr->next; } found: false

Finding a Possible Mercedes (cont.) start ptr item maker: Mercedes price: year: operator == … Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) // overloaded == found = true; if ( !found ) ptr = ptr->next; } found: false

Finding a Possible Mercedes (cont.) start ptr item maker: Mercedes price: year: operator == … Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) found = true; if ( !found ) ptr = ptr->next; } found: false

Finding a Possible Mercedes (cont.) start ptr item maker: Mercedes price: year: operator == … Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) found = true; if ( !found ) ptr = ptr->next; } found: false

Finding a Possible Mercedes (cont.) start ptr item maker: Mercedes price: year: operator == … Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) found = true; if ( !found ) ptr = ptr->next; } found: false

Finding a Possible Mercedes (cont.) start ptr item maker: Mercedes price: year: operator == … Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) found = true; if ( !found ) ptr = ptr->next; } found: false

Finding a Possible Mercedes (cont.) start ptr item maker: Mercedes price: year: operator == … Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) found = true; if ( !found ) ptr = ptr->next; } found: false Notice that found is only set to true if Mercedes is found …

Finding a Possible Mercedes (cont.) start ptr item maker: Mercedes price: year: operator == … Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) found = true; if ( !found ) ptr = ptr->next; } found: false then, !found is false and the loop exits

Finding a Possible Mercedes (cont.) start ptr item maker: Mercedes price: year: operator == … Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) found = true; if ( !found ) ptr = ptr->next; } found: false If Mercedes is not found, ptr eventually gets set to NULL, as before.

Finding a Possible Mercedes (cont.) start ptr item maker: Mercedes price: year: operator == … Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) found = true; if ( !found ) ptr = ptr->next; } found: false After going through the loop several times…

Finding a Possible Mercedes (cont.) start ptr item maker: Mercedes price: year: operator == … Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) found = true; if ( !found ) ptr = ptr->next; } found: false

Finding a Possible Mercedes (cont.) start ptr item maker: Mercedes price: year: operator == … Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) found = true; if ( !found ) ptr = ptr->next; } found: false

Finding a Possible Mercedes (cont.) start ptr is set to NULL item maker: Mercedes price: year: operator == … Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) found = true; if ( !found ) ptr = ptr->next; } found: false

Finding a Possible Mercedes (cont.) start ptr is set to NULL item maker: Mercedes price: year: operator == … Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) found = true; if ( !found ) ptr = ptr->next; } found: false

Finding a Possible Mercedes (cont.) start ptr is set to NULL item maker: Mercedes price: year: operator == … Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) found = true; if ( !found ) ptr = ptr->next; } found: false Exit from loop with no runtime error

Yet Another Case What if the linked list is empty to begin with? Try to consider all possible cases When a linked list is empty, the start pointer should always be set to NULL The start pointer would be set to NULL inside the constructor, when an empty linked list is first made

Empty List Case item start is set to NULL maker: Mercedes price: year: operator == Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) found = true; if ( !found ) ptr = ptr->next; }

Empty List Case (cont.) item start is set to NULL maker: Mercedes price: year: operator == Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) found = true; if ( !found ) ptr = ptr->next; } SAME CODE

Empty List Case (cont.) item start is set to NULL maker: Mercedes price: year: operator == Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) found = true; if ( !found ) ptr = ptr->next; }

Empty List Case (cont.) item start is set to NULL maker: Mercedes price: year: operator == ptr is set to NULL Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) found = true; if ( !found ) ptr = ptr->next; }

Empty List Case (cont.) item start is set to NULL maker: Mercedes price: year: operator == ptr is set to NULL Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) found = true; if ( !found ) ptr = ptr->next; }

Empty List Case (cont.) item start is set to NULL maker: Mercedes price: year: operator == ptr is set to NULL Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) found = true; if ( !found ) ptr = ptr->next; } found: false

Empty List Case (cont.) item start is set to NULL maker: Mercedes price: year: operator == ptr is set to NULL Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) found = true; if ( !found ) ptr = ptr->next; } found: false

Empty List Case (cont.) item start is set to NULL maker: Mercedes price: year: operator == ptr is set to NULL Node<DataType> *ptr = start; bool found = false; while (ptr != NULL && !found ) { if ( ptr->info == item ) found = true; if ( !found ) ptr = ptr->next; } found: false Exit loop without runtime error

Inserting a New Node Let’s assume that we want to insert a new node at the beginning of a linked list Assume that the client passes in a parameter called element (of type DataType) We would like to place the element into a node and insert the node at the beginning of the linked list

Inserting a Node element start

Inserting a Node (cont.) element start All new nodes must be made in the heap, SO…

Inserting a Node (cont.) element start Node<DataType> *ptr = new Node<DataType>;

Inserting a Node (cont.) element start ptr Node<DataType> *ptr = new Node<DataType>;

Inserting a Node (cont.) element start ptr Node<DataType> *ptr = new Node<DataType>; Now we have to store element into the node

Inserting a Node (cont.) element start ptr Node<DataType> *ptr = new Node<DataType>; ptr->info = element;

Inserting a Node (cont.) element start ptr Node<DataType> *ptr = new Node<DataType>; ptr->info = element;

Inserting a Node (cont.) element start ptr Node<DataType> *ptr = new Node<DataType>; ptr->info = element;

Inserting a Node (cont.) element start Now we have to think about how to make the pointer called “next” point to the first node in the list, to link it in ptr Node<DataType> *ptr = new Node<DataType>; ptr->info = element;

Inserting a Node (cont.) element start You can’t successfully write code like this without thinking about addresses. ptr Node<DataType> *ptr = new Node<DataType>; ptr->info = element;

Inserting a Node (cont.) element start REMEMBER…when you want to change the way a pointer points, you HAVE to assign a different address to it ptr Node<DataType> *ptr = new Node<DataType>; ptr->info = element;

Inserting a Node (cont.) element start Right now, the pointer called “next” doesn’t have a valid address assigned to it. ptr Node<DataType> *ptr = new Node<DataType>; ptr->info = element;

Inserting a Node (cont.) element start To store the correct address in it, we have to find the address of the first node of the linked list. ptr Node<DataType> *ptr = new Node<DataType>; ptr->info = element;

Inserting a Node (cont.) element start Where is the address of the first node stored? ptr Node<DataType> *ptr = new Node<DataType>; ptr->info = element;

Inserting a Node (cont.) element start Now think, the address would be stored in something that points to it. So where is it stored? ptr Node<DataType> *ptr = new Node<DataType>; ptr->info = element;

Inserting a Node (cont.) element start ptr That’s right, in the start pointer. Node<DataType> *ptr = new Node<DataType>; ptr->info = element;

Inserting a Node (cont.) element start So now, all we have to do is copy that address into the pointer called “next” ptr Node<DataType> *ptr = new Node<DataType>; ptr->info = element;

Inserting a Node (cont.) element start ptr Node<DataType> *ptr = new Node<DataType>; ptr->info = element;

Inserting a Node (cont.) element start ptr Node<DataType> *ptr = new Node<DataType>; ptr->info = element; ptr->next = start;

Inserting a Node (cont.) element start ptr Node<DataType> *ptr = new Node<DataType>; ptr->info = element; ptr->next = start;

Inserting a Node (cont.) element start Well, it’s been inserted. But start should point to the first node now. ptr Node<DataType> *ptr = new Node<DataType>; ptr->info = element; ptr->next = start;

Inserting a Node (cont.) element start REMEMBER…when you want to change the way a pointer points, you have to assign a different address to it ptr Node<DataType> *ptr = new Node<DataType>; ptr->info = element; ptr->next = start;

Inserting a Node (cont.) element start We’d like start to point to the new node, so what stores the address of the new node? ptr Node<DataType> *ptr = new Node<DataType>; ptr->info = element; ptr->next = start;

Inserting a Node (cont.) element start That’s right, ptr. So now all we have to do is assign the address stored in ptr to the start pointer. ptr Node<DataType> *ptr = new Node<DataType>; ptr->info = element; ptr->next = start;

Inserting a Node (cont.) element start ptr Node<DataType> *ptr = new Node<DataType>; ptr->info = element; ptr->next = start;

Inserting a Node (cont.) element start ptr Node<DataType> *ptr = new Node<DataType>; ptr->info = element; ptr->next = start; start = ptr;

Inserting a Node (cont.) element start ptr Node<DataType> *ptr = new Node<DataType>; ptr->info = element; ptr->next = start; start = ptr;

Inserting a Node (cont.) element start ptr Easy, right? Node<DataType> *ptr = new Node<DataType>; ptr->info = element; ptr->next = start; start = ptr;

REMEMBER… Use drawings when working with linked lists, until you become an expert When you want to change the way a pointer points, you have to assign a different address to it You can find the address you need by looking at other pointers (remember that they store addresses)

Inserting into the Middle of a Linked List Suppose we know that there is a Mercedes in a linked list We would like to insert a node containing Honda right after it We first find the Mercedes, using code that we looked at before

Inserting a Node start element maker: Mercedes price: year: operator != … Mercedes Node<DataType> *ptr = start; while ( ptr->info != element ) // element is a parameter ptr = ptr->next;

Inserting a Node (cont.) start element maker: Mercedes price: year: operator != … Mercedes After this code executes, ptr points to the node that has Mercedes. Node<DataType> *ptr = start; while ( ptr->info != element ) // element is a parameter ptr = ptr->next;

Inserting a Node (cont.) start element ptr maker: Mercedes price: year: operator != … Mercedes After this code executes, ptr points to the node that has Mercedes. Node<DataType> *ptr = start; while ( ptr->info != element ) // element is a parameter ptr = ptr->next;

Inserting a Node (cont.) start element ptr maker: Mercedes price: year: operator != … Mercedes Now we would like to insert a CarType object called elementToInsert (containing Honda), which would also be passed in as a parameter, right after the Mercedes

Inserting a Node (cont.) start ptr maker: Honda price: 5000 year: 1985 operator != … Mercedes elementToInsert

Inserting a Node (cont.) start ptr maker: Honda price: 5000 year: 1985 operator != … Mercedes elementToInsert Well, all new nodes are created in the heap, SO…..

Inserting a Node (cont.) start ptr maker: Honda price: 5000 year: 1985 operator != … Mercedes elementToInsert Node<DataType> *newNode = new Node<DataType>;

Inserting a Node (cont.) start ptr maker: Honda price: 5000 year: 1985 operator != … Mercedes elementToInsert newNode Node<DataType> *newNode = new Node<DataType>;

Inserting a Node (cont.) start ptr maker: Honda price: 5000 year: 1985 operator != … Mercedes elementToInsert newNode Node<DataType> *newNode = new Node<DataType>; Now, how about placing elementToInsert into the new node?

Inserting a Node (cont.) start ptr maker: Honda price: 5000 year: 1985 operator != … Mercedes elementToInsert newNode Node<DataType> *newNode = new Node<DataType>; newNode->info = elementToInsert;

Inserting a Node (cont.) start ptr maker: Honda price: 5000 year: 1985 operator != … Mercedes elementToInsert newNode Node<DataType> *newNode = new Node<DataType>; newNode->info = elementToInsert;

Inserting a Node (cont.) start ptr maker: Honda price: 5000 year: 1985 operator != … Mercedes elementToInsert newNode Node<DataType> *newNode = new Node<DataType>; newNode->info = elementToInsert;

Inserting a Node (cont.) start ptr … Mercedes newNode Node<DataType> *newNode = new Node<DataType>; newNode->info = elementToInsert;

Inserting a Node (cont.) start ptr Now, what we want is shown by the dashed arrows; this would cause the insertion of the node … Mercedes newNode Node<DataType> *newNode = new Node<DataType>; newNode->info = elementToInsert;

Inserting a Node (cont.) start ptr We have two pointers we need to change – but we have to be careful about the way we change them … Mercedes newNode Node<DataType> *newNode = new Node<DataType>; newNode->info = elementToInsert;

Inserting a Node (cont.) start ptr If we change the left pointer first, we will no longer be able to access the last node (memory leak) … Mercedes newNode Node<DataType> *newNode = new Node<DataType>; newNode->info = elementToInsert;

Inserting a Node (cont.) start ptr So, we first have to assign the address of the last node into the “next” pointer of the new node … Mercedes newNode Node<DataType> *newNode = new Node<DataType>; newNode->info = elementToInsert;

Inserting a Node (cont.) start ptr Where is the address of the last node stored? … Mercedes newNode Node<DataType> *newNode = new Node<DataType>; newNode->info = elementToInsert;

Inserting a Node (cont.) start ptr That’s right, it is stored in ptr->next … Mercedes newNode Node<DataType> *newNode = new Node<DataType>; newNode->info = elementToInsert;

Inserting a Node (cont.) start ptr … Mercedes newNode Node<DataType> *newNode = new Node<DataType>; newNode->info = elementToInsert; newNode->next = ptr->next;

Inserting a Node (cont.) start ptr … Mercedes newNode Node<DataType> *newNode = new Node<DataType>; newNode->info = elementToInsert; newNode->next = ptr->next;

Inserting a Node (cont.) start ptr … Mercedes newNode Node<DataType> *newNode = new Node<DataType>; newNode->info = elementToInsert; newNode->next = ptr->next; ptr->next = newNode;

Inserting a Node (cont.) start ptr … Mercedes Mercedes newNode Node<DataType> *newNode = new Node<DataType>; newNode->info = elementToInsert; newNode->next = ptr->next; ptr->next = newNode;

Removing a Node Suppose we definitely know there is a Mercedes in the linked list and we wish to remove the node that contains it We need to find the node first

Removing a Node (cont.) start … Mercedes

Removing a Node (cont.) ptr start … Mercedes

Removing a Node (cont.) ptr start … Mercedes When it is found, we need to join the node in front of it to the node after it.

Removing a Node (cont.) ptr start … Mercedes When it is found, we need to join the node in front of it to the node after it.

Removing a Node (cont.) ptr start … Mercedes But how can we access the “next” pointer of the node in front, so we can change the address it stores? (we can’t)

Removing a Node (cont.) ptr start … Mercedes The way to solve the problem is by having ptr stop on the node BEFORE the node that has Mercedes

Removing a Node (cont.) ptr start … Mercedes

Removing a Node (cont.) ptr start … Mercedes

Removing a Node (cont.) ptr start … Mercedes If ptr stops here, then we CAN change the address stored in the “next” pointer. So we have to set up a loop appropriately.

Removing a Node (cont.) start … Mercedes

Removing a Node (cont.) start … element contains Mercedes Node<DataType> *ptr = start; while ( ptr->next->info != element ) // overloaded != operator ptr = ptr->next;

Removing a Node (cont.) start … Mercedes passed in from the client as a parameter Node<DataType> *ptr = start; while ( ptr->next->info != element ) // overloaded != operator ptr = ptr->next;

Removing a Node (cont.) start … Node<DataType> *ptr = start; Mercedes Node<DataType> *ptr = start; while ( ptr->next->info != element ) // overloaded != operator ptr = ptr->next;

Removing a Node (cont.) start … Mercedes BUT…what if Mercedes is in the first node? Node<DataType> *ptr = start; while ( ptr->next->info != element ) // overloaded != operator ptr = ptr->next;

Removing a Node (cont.) start … Mercedes BUT…what if Mercedes is in the first node? Node<DataType> *ptr = start; while ( ptr->next->info != element ) // overloaded != operator ptr = ptr->next;

Removing a Node (cont.) start … Mercedes We need to handle the first node differently. Node<DataType> *ptr = start; while ( ptr->next->info != element ) // overloaded != operator ptr = ptr->next;

Removing a Node (cont.) start … Mercedes

Removing a Node (cont.) start … Node<DataType> *ptr = start; Mercedes Node<DataType> *ptr = start; if ( ptr->info == element ) start = start->next;

Removing a Node (cont.) start … Node<DataType> *ptr = start; Mercedes Node<DataType> *ptr = start; if ( ptr->info == element ) start = start->next;

Removing a Node (cont.) ptr start … Node<DataType> *ptr = start; Mercedes Node<DataType> *ptr = start; if ( ptr->info == element ) start = start->next;

Removing a Node (cont.) ptr start … Node<DataType> *ptr = start; Mercedes Node<DataType> *ptr = start; if ( ptr->info == element ) start = start->next;

Removing a Node (cont.) ptr start … Node<DataType> *ptr = start; Mercedes Node<DataType> *ptr = start; if ( ptr->info == element ) start = start->next;

Removing a Node (cont.) ptr start … Node<DataType> *ptr = start; Mercedes Node<DataType> *ptr = start; if ( ptr->info == element ) start = start->next;

Removing a Node (cont.) ptr start … Mercedes Well, start points to the beginning of the new linked list, but a node isn’t removed unless we free it. Node<DataType> *ptr = start; if ( ptr->info == element ) start = start->next;

Removing a Node (cont.) ptr start … Node<DataType> *ptr = start; Mercedes Node<DataType> *ptr = start; if ( ptr->info == element ) start = start->next;

Removing a Node (cont.) ptr start … Node<DataType> *ptr = start; Mercedes Node<DataType> *ptr = start; if ( ptr->info == element ) { start = start->next; delete ptr; }

Removing a Node (cont.) ptr start … Node<DataType> *ptr = start; Mercedes Node<DataType> *ptr = start; if ( ptr->info == element ) { start = start->next; delete ptr; }

Removing a Node (cont.) ptr start … Node<DataType> *ptr = start; if ( ptr->info == element ) { start = start->next; delete ptr; }

Removing a Node (cont.) ptr start … Node<DataType> *ptr = start; if ( ptr->info == element ) { start = start->next; delete ptr; } Now, let’s consider the other case.

Removing a Node (cont.) start … Mercedes

Removing a Node (cont.) start … else { Mercedes else { while ( ptr->next->info != element ) ptr = ptr->next;

Removing a Node (cont.) start … else { Mercedes else { while ( ptr->next->info != element ) ptr = ptr->next; This is the loop that we thought of before.

Removing a Node (cont.) start … else { Mercedes else { while ( ptr->next->info != element ) ptr = ptr->next; It will find the node BEFORE the node that has Mercedes.

Removing a Node (cont.) ptr start … else { Mercedes else { while ( ptr->next->info != element ) ptr = ptr->next; It will find the node BEFORE the node that has Mercedes.

Removing a Node (cont.) ptr start … Mercedes else { while ( ptr->next->info != element ) ptr = ptr->next; Now we need to join the node before Mercedes to the node after Mercedes

Removing a Node (cont.) ptr start … else { Mercedes else { while ( ptr->next->info != element ) ptr = ptr->next;

Removing a Node (cont.) ptr start … else { Mercedes else { while ( ptr->next->info != element ) ptr = ptr->next; ptr->next = ptr->next->next;

Removing a Node (cont.) ptr start … else { Mercedes else { while ( ptr->next->info != element ) ptr = ptr->next; ptr->next = ptr->next->next;

Removing a Node (cont.) ptr start … else { Mercedes else { while ( ptr->next->info != element ) ptr = ptr->next; ptr->next = ptr->next->next;

Removing a Node (cont.) ptr start … else { Mercedes else { while ( ptr->next->info != element ) ptr = ptr->next; ptr->next = ptr->next->next;

Removing a Node (cont.) ptr start … else { Mercedes else { while ( ptr->next->info != element ) ptr = ptr->next; ptr->next = ptr->next->next; But how will we free the node that has Mercedes?

Removing a Node (cont.) ptr start … else { Mercedes else { while ( ptr->next->info != element ) ptr = ptr->next; ptr->next = ptr->next->next; This is memory leak. We better back up.

Removing a Node (cont.) ptr start … else { Mercedes else { while ( ptr->next->info != element ) ptr = ptr->next;

Removing a Node (cont.) ptr start … else { Mercedes else { while ( ptr->next->info != element ) ptr = ptr->next; Node<DataType> *ptr2 = ptr->next;

Removing a Node (cont.) ptr start … else { Mercedes else { while ( ptr->next->info != element ) ptr = ptr->next; Node<DataType> *ptr2 = ptr->next;

Removing a Node (cont.) ptr ptr2 start … else { Mercedes else { while ( ptr->next->info != element ) ptr = ptr->next; Node<DataType> *ptr2 = ptr->next;

Removing a Node (cont.) ptr ptr2 start … Mercedes else { while ( ptr->next->info != element ) ptr = ptr->next; Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next;

Removing a Node (cont.) ptr ptr2 start … Mercedes else { while ( ptr->next->info != element ) ptr = ptr->next; Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next;

Removing a Node (cont.) ptr ptr2 start … Mercedes else { while ( ptr->next->info != element ) ptr = ptr->next; Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2;

Removing a Node (cont.) ptr ptr2 start … else { while ( ptr->next->info != element ) ptr = ptr->next; Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2;

Removing a Node (cont.) ptr ptr2 start … else { while ( ptr->next->info != element ) ptr = ptr->next; Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2; }

Removing a Node (cont.) ptr ptr2 start … We did it! else { while ( ptr->next->info != element ) ptr = ptr->next; Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2; } We did it!

What If? What if Mercedes is the last node in the linked list Would our code still work? Try to consider every possible situation in code design

Removing the Last Node ptr start … Mercedes else { while ( ptr->next->info != element ) ptr = ptr->next; Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2; } After looping, ptr stops on the next-to-the-last node

Removing the Last Node (cont.) ptr start … Mercedes else { while ( ptr->next->info != element ) ptr = ptr->next; Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2; }

Removing the Last Node (cont.) ptr ptr2 start … Mercedes else { while ( ptr->next->info != element ) ptr = ptr->next; Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2; }

Removing the Last Node (cont.) ptr ptr2 start … Mercedes else { while ( ptr->next->info != element ) ptr = ptr->next; Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2; }

Removing the Last Node (cont.) ptr ptr2 start … Mercedes else { while ( ptr->next->info != element ) ptr = ptr->next; Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2; }

Removing the Last Node (cont.) ptr ptr2 start … Mercedes else { while ( ptr->next->info != element ) ptr = ptr->next; Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2; }

Removing the Last Node (cont.) ptr ptr2 start … else { while ( ptr->next->info != element ) ptr = ptr->next; Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2; }

Removing the Last Node (cont.) ptr ptr2 start … else { while ( ptr->next->info != element ) ptr = ptr->next; Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2; } The code works in removing the last node.

Working With Linked Lists As you can see, sometimes you have to do a lot of thinking and problem-solving when working with linked lists It is not always obvious how to write code You can’t memorize the code, because it will not quite fit situations that you will encounter It is a matter of using logic (and knowing a few tricks of the trade)

Code for Removing a Node Here is the resulting code for removing a node. It is assumes the node we are looking for is in the linked list. 1 Node<DataType> *ptr = start; 2 if ( ptr->info == element ) { 3 start = start->next; 4 delete ptr; 5 } 6 else { 7 while ( ptr->next->info != element ) 8 ptr = ptr->next; 9 Node<DataType> *ptr2 = ptr->next; 10 ptr->next = ptr2->next; 11 delete ptr2; 12 }

Code for Removing a Node (cont.) 1 Node<DataType> *ptr = start; 2 if ( ptr->info == element ) { 3 start = start->next; 4 delete ptr; 5 } 6 else { 7 while ( ptr->next->info != element ) 8 ptr = ptr->next; 9 Node<DataType> *ptr2 = ptr->next; 10 ptr->next = ptr2->next; 11 delete ptr2; 12 } This code can be simplified by using a header node…

Code for Removing a Node (cont.) 1 Node<DataType> *ptr = start; 2 if ( ptr->info == element ) { 3 start = start->next; 4 delete ptr; 5 } 6 else { 7 while ( ptr->next->info != element ) 8 ptr = ptr->next; 9 Node<DataType> *ptr2 = ptr->next; 10 ptr->next = ptr2->next; 11 delete ptr2; 12 } A header node is like any other node, except it doesn’t contain data.

Code for Removing a Node (cont.) 1 Node<DataType> *ptr = start; 2 if ( ptr->info == element ) { 3 start = start->next; 4 delete ptr; 5 } 6 else { 7 while ( ptr->next->info != element ) 8 ptr = ptr->next; 9 Node<DataType> *ptr2 = ptr->next; 10 ptr->next = ptr2->next; 11 delete ptr2; 12 } It is formed with the Node struct, like any other node, but the info data member isn’t set to anything.

Code for Removing a Node (cont.) 1 Node<DataType> *ptr = start; 2 if ( ptr->info == element ) { 3 start = start->next; 4 delete ptr; 5 } 6 else { 7 while ( ptr->next->info != element ) 8 ptr = ptr->next; 9 Node<DataType> *ptr2 = ptr->next; 10 ptr->next = ptr2->next; 11 delete ptr2; 12 } The header node would be the first node in the linked list.

Code for Removing a Node (cont.) 1 Node<DataType> *ptr = start; 2 if ( ptr->info == element ) { 3 start = start->next; 4 delete ptr; 5 } 6 else { 7 while ( ptr->next->info != element ) 8 ptr = ptr->next; 9 Node<DataType> *ptr2 = ptr->next; 10 ptr->next = ptr2->next; 11 delete ptr2; 12 } The header node eliminates this special case…

Code for Removing a Node (cont.) 1 Node<DataType> *ptr = start; 2 if ( ptr->info == element ) { 3 start = start->next; 4 delete ptr; 5 } 6 else { 7 while ( ptr->next->info != element ) 8 ptr = ptr->next; 9 Node<DataType> *ptr2 = ptr->next; 10 ptr->next = ptr2->next; 11 delete ptr2; 12 } Since we know the first node doesn’t contain data, it can’t contain Mercedes.

Code with Header Node 1 Node<DataType> *ptr = start; 2 while ( ptr->next->info != element ) 3 ptr = ptr->next; 4 Node<DataType> *ptr2 = ptr->next; 5 ptr->next = ptr2->next; 6 delete ptr2;

Removing a Node But this code assumes that there definitely is a Mercedes in the linked list Let’s refine it a little Suppose we are not really sure if there is a Mercedes in the linked list to delete Or suppose the linked list is empty to begin with Always try to handle every case

Refining Code with Header Node Node<DataType> *ptr = start; while ( ptr->next->info != element ) ptr = ptr->next; Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2;

Refining Code with Header Node (cont.) Node<DataType> *ptr = start; while ( ptr->next->info != element ) ptr = ptr->next; Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2; We’ll use our found variable, like before.

Refining Code with Header Node (cont.) Node<DataType> *ptr = start; bool found = false; while ( ptr->next->info != element ) ptr = ptr->next; Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2; We’ll use our found variable, like before.

Refining Code with Header Node (cont.) Node<DataType> *ptr = start; bool found = false; while ( ptr->next->info != element ) ptr = ptr->next; Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2; An empty list just has a header node.

Refining Code with Header Node (cont.) Node<DataType> *ptr = start; bool found = false; while ( ptr->next->info != element ) ptr = ptr->next; Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2; This will give us a runtime error if we have an empty list. Let’s test for it in a loop heading.

Refining Code with Header Node (cont.) Node<DataType> *ptr = start; bool found = false; while ( ptr->next->info != element ) ptr = ptr->next; Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2; We’ll make a new loop and shove this part inside.

Refining Code with Header Node (cont.) Node<DataType> *ptr = start; bool found = false; while ( ptr->next != NULL ) { while ( ptr->next->info != element ) ptr = ptr->next; Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2; }

Refining Code with Header Node (cont.) Node<DataType> *ptr = start; bool found = false; while ( ptr->next != NULL ) { while ( ptr->next->info != element ) ptr = ptr->next; Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2; } Now we want the removal code if ptr->next->info IS equal to element

Refining Code with Header Node (cont.) Node<DataType> *ptr = start; bool found = false; while ( ptr->next != NULL ) { if ( ptr->next->info == element ) ptr = ptr->next; Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2; } Now we want the removal code if ptr->next->info IS equal to element

Refining Code with Header Node (cont.) Node<DataType> *ptr = start; bool found = false; while ( ptr->next != NULL ) { if ( ptr->next->info == element ) { Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2; }

Refining Code with Header Node (cont.) Node<DataType> *ptr = start; bool found = false; while ( ptr->next != NULL ) { if ( ptr->next->info == element ) { Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2; } If we remove a node, we need to break out of the loop.

Refining Code with Header Node (cont.) Node<DataType> *ptr = start; bool found = false; while ( ptr->next != NULL && !found ) { if ( ptr->next->info == element ) { Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2; found = true; } If we remove a node, we need to break out of the loop.

Refining Code with Header Node (cont.) Node<DataType> *ptr = start; bool found = false; while ( ptr->next != NULL && !found ) { if ( ptr->next->info == element ) { Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2; found = true; } Now, we just need to advance ptr if we didn’t remove a node.

Refining Code with Header Node (cont.) Node<DataType> *ptr = start; bool found = false; while ( ptr->next != NULL && !found ) { if ( ptr->next->info == element ) { Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2; found = true; } if ( !found ) ptr = ptr->next; Now, we just need to advance ptr if we didn’t remove a node.

Refining Code with Header Node (cont.) Node<DataType> *ptr = start; bool found = false; while ( ptr->next != NULL && !found ) { if ( ptr->next->info == element ) { Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2; found = true; } if ( !found ) ptr = ptr->next; If ptr is pointing to the last node when this condition is checked, Mercedes can’t be in the last node…

Refining Code with Header Node (cont.) Node<DataType> *ptr = start; bool found = false; while ( ptr->next != NULL && !found ) { if ( ptr->next->info == element ) { Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2; found = true; } if ( !found ) ptr = ptr->next; It would have been found on the previous iteration. Therefore, we break out of the loop at the right time.

Refining Code with Header Node (cont.) Node<DataType> *ptr = start; bool found = false; while ( ptr->next != NULL && !found ) { if ( ptr->next->info == element ) { Node<DataType> *ptr2 = ptr->next; ptr->next = ptr2->next; delete ptr2; found = true; } if ( !found ) ptr = ptr->next; Final result.

Linked List vs. Arrays When computer scientists decide on whether or not to use an array or linked list for data, the decision is usually based on two factors: Speed Conservation of Memory (RAM)

Speed In some situations, an array can be faster than a linked list, such as when a calculated index is used to access an element In other situations, a linked list can be faster than an array, such as when removing an element from the middle (as we saw before) we usually need to search for the element to remove, but we search for it in both the array and linked list

Memory Conservation start Linked List with Element Size of 32 Bytes

Memory Conservation (cont.) When evaluating memory conservation between linked lists and arrays, we make use of dynamic space and static space within elements, which are usually records of information dynamic space – uses heap memory (example: the dynamic character array for a string) static space – space not in heap memory We also assume the array expansion/contraction scheme described earlier

Memory Conservation (cont.) We may have three types of elements used in arrays: never-used elements (won’t have dynamic space) previously-used elements (may have dynamic space, but these elements are made inaccessible) used elements (may have dynamic space)

Memory Conservation (cont.) Let h be the amount of housekeeping space within a linked list node (example: the “next” pointer) Let s be the amount of static space Let e be the total amount of space in an element (both static and dynamic space) Then, we have three cases to consider…

Memory Conservation (cont.) Case I. If there is only static space within elements (no dynamic space), then: (1) if the element size is less than h, the array is expected to waste less memory than the linked list (2) if the element size is more than 3h, the linked list is expected to waste less memory than the array (3) if the element size is between h and 3h, there may not be a significant difference in wasting memory between the array and linked list

Memory Conservation (cont.) Case II. If we would only add elements to the data structure and never remove them (so that we never have previously-used elements), and dynamic space may be used in elements, then: (1) if h < s/3, the linked list is expected to waste less memory than the array (2) if h > s/3, the array is expected to waste less memory than the linked list (3) if h = s/3, then there may not be a significant difference in wasting memory between the array and the linked list.

Memory Conservation (cont.) Case III. If there are all three types of elements during the use of the array, and dynamic space is used in elements, then: (1) if h < s/3, the linked list is expected to waste less memory than the array (2) if h > e, the array is expected to waste less memory than the linked list (3) if s/3  h  e, then there may not be a significant difference in wasting memory between the array and the linked list

Additional Notes About These Cases Case II is the most precise, and so it should be used when applicable Case III is really a generalization of Case I case I is case III with s = e (no dynamic space) case I is provided to avoid confusion Analysis about these cases is provided in the text