Download presentation
Presentation is loading. Please wait.
1
Linked Lists
2
Outline In this lesson, we will: Create a linked list class
Implement numerous member functions Explain how to step through a linked list
3
Nodes with member functions
Review our node class Holds an integer datum class Node; class Node { public: // Member functions to access private member variables Node( int value, Node *p_next = nullptr ); int get_value() const; Node *get_next() const; private: // Let's make them private now ... int node_value; Node *p_next_node; }; int Node::get_value() const { return node_value; } Node *Node::get_next() const { return p_next_node;
4
The need for a linked list class
A linked list of nodes is, however, difficult to deal with How and were do we add new nodes? Must we do this manually? We will create a linked list class that Stores the address of the first node Has member functions allowing us to access and manipulate the nodes in the linked list
5
Linked lists Now we introduce a Linked_list class: class Node;
class Linked_list; class Linked_list { public: Linked_list(); // Constructor ~Linked_list(); // Destructor private: Node *p_list_head; // Pointer to head node };
6
Constructor and destructor
Constructor initializes the pointer to the head of the list Linked_list::Linked_list(): p_list_head{nullptr} { // Nothing else for the constructor to do } The destructor needs to delete the linked list, but how… Linked_list::~Linked_list() { // To be completed later!!!
7
Empty query Implement a public member function to check if the linked list is empty If p_list_head equals nullptr, the linked list is empty class Linked_list { public: Linked_list(); ~Linked_list(); // Public member functions bool empty() const; private: Node *p_list_head; }; bool Linked_list::empty() const { return ( nullptr == p_list_head ); }
8
Inserting node We can insert a node into the linked list at the front of the list Introduce a public member function that inserts an integer at the front of the linked list void push_front( int datum ); class Linked_list { public: Linked_list(); ~Linked_list(); // Public member functions bool empty() const; private: Node *p_list_head; };
9
Inserting node There are two situations we may encounter when inserting a node at the front of a linked list The linked list is empty The linked list has at least one node
10
Inserting into an empty linked list
When inserting (say, 42) into an empty linked list, we want this The steps involved are: Creating a new node storing the new datum that points to null Assigns the address of the new node to p_list_head
11
Inserting into an empty linked list
We can do both in one step: void Linked_list::push_front( int datum ) { if ( empty() ) { // This list is empty p_list_head = new Node{datum, nullptr}; } else { // This list is not empty }
12
Inserting into a non-empty linked list
When inserting (say, 42) into a non-empty linked list, we want this The steps involved are: Creating a new node storing the new datum that points to what p_list_head used to be storing Assigns the address of the new node to p_list_head
13
Inserting into a non-empty linked list
We can do both of these, too, in one step: void Linked_list::push_front( int datum ) { if ( empty() ) { // The list is empty p_list_head = new Node{datum, nullptr}; } else { // List is not empty p_list_head = new Node{datum, p_list_head}; }
14
Inserting a node Consider this, however: We can simplify this to:
Even when the linked list was empty, p_list_head is assigned the address we need, namely nullptr: void Linked_list::push_front( int datum ) { if ( empty() ) { // The list is empty p_list_head = new Node{datum, nullptr}; } else { // List is not empty p_list_head = new Node{datum, p_list_head}; } We can simplify this to:
15
Accessing the value at the front
We want the integer stored in the node at the front class Linked_list { public: Linked_list(); // Constructor ~Linked_list(); // Destructor // Public member functions bool empty() const; void push_front( int datum ); int front() const; private: Node *p_list_head; // Pointer to head node };
16
Accessing the value at the front
Suppose we want to access the first node: If a node exists, return its value Otherwise, it is nullptr Throw an exception in that case int Linked_list::front() const { if ( empty() ) { std::cerr << "Error: list is empty" << std::endl; throw nullptr; } else { return p_list_head->get_value(); }
17
Creating a linked list Output: 150 105
class Node; class Linked_list; int main(); int main() { Linked_list list{}; list.push_front( 150 ); std::cout << list.front() << std::endl; list.push_front( 105 ); // What happens to the nodes? return 0; } Output: 150 105
18
Counting number of nodes in linked list
Suppose we want the number of nodes in the linked list This is the size of the linked list We must step through the linked list, counting the nodes as we pass through them Set a counter to zero Assign a temporary pointer p_current_node the address assigned to p_list_head While p_current_node does not equal nullptr Increment the counter Set p_current_node the address of p_current_node->get_next()
19
Counting number of nodes in linked list
We will do this in a function size(): std::size_t Linked_list::size() const { size_t list_size{0}; Node *p_current_node{p_list_head}; while ( p_current_node != nullptr ) { ++list_size; p_current_node = p_current_node->get_next(); } return list_size;
20
Counting number of nodes in linked list
Alternatively, we could use a for loop: std::size_t Linked_list::size() const { std::size_t list_size{0}; for ( Node *p_current_node{p_list_head}; p_current_node != nullptr; p_current_node = p_current_node->get_next() ) { ++list_size; } return list_size; std::size_t Linked_list::size() const { size_t list_size{0}; Node *p_current_node{p_list_head}; while ( p_current_node != nullptr ) { ++list_size; p_current_node = p_current_node->get_next(); } return list_size;
21
Printing the linked list
Using this same format, we can print a linked list: void Linked_list::print() const { std::cout << "p_list_head -> "; for ( Node *p_current_node{p_list_head}; p_current_node != nullptr; p_current_node = p_current_node->get_next() ) { std::cout << "(" << p_current_node->get_value() << ") -> "; } std::cout << "0" << std::endl;
22
Finding a value Using this same format, we can also find a value in a linked list: // Returns size() if the value was not found std::size_t Linked_list::find( int datum ) const { std::size_t position{0}; for ( Node *p_current_node{p_list_head}; (p_current_node != nullptr) && (p_current_node->get_value() != datum); p_current_node = p_current_node->get_next() ) { ++position; } return position;
23
Creating a linked list class Node; class Linked_list; int main(); int main() { Linked_list list{}; list.push_front( 150 ); list.push_front( 105 ); std::cout << "Size: " << list.size() << std::endl; list.print(); // What happens to the nodes? return 0; } Output: Size: 2 p_list_head -> (105) -> (150) -> 0
24
Erasing a node To remove a node from the front of a linked list, we require a pop_front() member function We will return true or false, depending on whether or not we were successful in erasing the front node We may encounter three situations when erasing a node: The linked list may be empty There may be only one node in the linked list There may be more than one node in the linked list
25
Popping from an empty list
If the linked list is empty, there is no node to pop: bool Linked_list::pop_front() { if ( empty() ) { return false; } else if ( 1 == size() ) { // Delete the one node in the linked list } else { assert( size() > 1 ); // Delete the node at the head of the list }
26
Popping from a linked list with one node
Suppose there is only one node in the linked list: We must: Delete the node at the front of the linked list Set p_list_head the value nullptr Return true
27
Popping from a linked list with one node
Erasing one node is reasonably straight-forward: bool Linked_list::pop_front() { if ( empty() ) { return false; } else if ( 1 == size() ) { // Delete the one node in the linked list delete p_list_head; p_list_head = nullptr; return true; } else { assert( size() > 1 ); // Delete the node at the head of the list }
28
Popping from a linked list with many nodes
Suppose there are many nodes in the linked list: We must: Delete the node at the front of the linked list Set p_list_head the address of the node pointed to by what used to be the node at the front Return true
29
Popping from a linked list with many nodes
Does this work? bool Linked_list::pop_front() { if ( empty() ) { return false; } else if ( 1 == size() ) { // Delete the one node in the linked list delete p_list_head; p_list_head = nullptr; return true; } else { assert( size() > 1 ); p_list_head = p_list_head->get_next(); }
30
Popping from a linked list with many nodes
How about this? bool Linked_list::pop_front() { if ( empty() ) { return false; } else if ( 1 == size() ) { // Delete the one node in the linked list delete p_list_head; p_list_head = nullptr; return true; } else { assert( size() > 1 ); p_list_head = p_list_head->get_next(); delete ???; }
31
Popping from a linked list with many nodes
Instead, we must: Temporarily store the address of the front node Update the pointer to the list head The delete the old node
32
Popping from a linked list with many nodes
Implementing this: bool Linked_list::pop_front() { if ( empty() ) { return false; } else if ( 1 == size() ) { // Delete the one node in the linked list delete p_list_head; p_list_head = nullptr; return true; } else { assert( size() > 1 ); Node *p_previous_list_head{p_list_head}; p_list_head = p_list_head->get_next(); delete p_previous_list_head; }
33
Popping from a linked list with many nodes
Now, if the list has only one entry: p_list_head->get_next() is assigned nullptr Calling delete on nullptr is a valid C++ operation that does nothing Simplifying our implementation: bool Linked_list::pop_front() { if ( empty() ) { return false; } else { assert( size() >= 1 ); Node *p_previous_list_head{p_list_head}; p_list_head = p_list_head->get_next(); delete p_previous_list_head; return true; }
34
Clearing all nodes in a list
Suppose we want to empty a non-empty linked list We must pop each node in the linked list Here is the hard way: void Linked_list::clear() { while ( p_list_head != nullptr ) { Node *p_previous_list_head{p_list_head}; p_list_head = p_current_node->get_next(); delete p_previous_list_head; }
35
Clearing all nodes in a list
Question: Why not use member functions we already wrote: void Linked_list::clear() { while ( !empty() ) { pop_front(); }
36
Destructor We can now author a destructor:
Linked_list::~Linked_list() { clear(); }
37
Linked lists Here is our Linked_list class so far: class Node;
class Linked_list; class Linked_list { public: Linked_list(); // Constructor ~Linked_list(); // Destructor bool empty() const; std::size_t size() const; int front() const; void print() const; std::size_t find( int datum ) const; void push_front( int datum ); bool pop_front(); void clear(); private: Node *p_list_head; // Pointer to head node };
38
Summary Following this lesson, you now
Know how to create a simple linked list class Understand how member functions can implement most of the operations in question Know how to step through a linked list
39
References [1] No references?
40
Colophon These slides were prepared using the Georgia typeface. Mathematical equations use Times New Roman, and source code is presented using Consolas. The photographs of lilacs in bloom appearing on the title slide and accenting the top of each other slide were taken at the Royal Botanical Gardens on May 27, 2018 by Douglas Wilhelm Harder. Please see for more information.
41
Disclaimer These slides are provided for the ece 150 Fundamentals of Programming course taught at the University of Waterloo. The material in it reflects the authors’ best judgment in light of the information available to them at the time of preparation. Any reliance on these course slides by any party for any other purpose are the responsibility of such parties. The authors accept no responsibility for damages, if any, suffered by any party as a result of decisions made or actions based on these course slides for any other purpose than that for which it was intended.
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.