Presentation is loading. Please wait.

Presentation is loading. Please wait.

Templated Linked Lists

Similar presentations


Presentation on theme: "Templated Linked Lists"— Presentation transcript:

1 Templated Linked Lists

2 Outline In this lesson, we will:
Convert our linked list of int to one using templates

3 Included libraries We will require three libraries:
#include <cstdlib> #include <iostream> #include <cassert>

4 Nodes with member functions
Recall that the only places we used the datatype int was when: We declared the member variable holding the datum Declared the member functions: Pushing a new node at the front or the back Returning the front or the back Finding a datum in the linked list These are ideal conditions for a templated: Both the Node and the Linked_list classes must be templated

5 The Node class The modifications to the Node class are straight-forward: // Class declarations template <typename T> class Node; class Linked_list; // Class definitions class Node { public: Node( T value, Node *p_next = nullptr ); T get_value() const; Node *get_next() const; private: T node_value; Node *p_next_node; template <typename S> friend class Linked_list; }; template <typename T> Node<T>::Node( T value, Node *p_next ): node_value{value}, p_next_node{p_next} { // Empty constructor } T Node<T>::get_value() const { return node_value; Node<T> *Node<T>::get_next() const { return p_next_node;

6 The Linekd list class The modifications to the Node class are straight-forward: template <typename T> class Linked_list { public: Linked_list(); ~Linked_list(); bool empty() const; std::size_t size() const; T front() const; T back() const; void print() const; std::size_t find( T datum ) const; void push_front( T datum ); void push_front( Linked_list &list ); void push_back( T datum ); void push_back( Linked_list &list ); bool pop_front(); void clear(); private: Node<T> *p_list_head; Node<T> *p_list_tail; std::size_t list_size; };

7 The Linekd list class There are no changes to the constructors, other than indicating the linked list is templated template <typename T> Linked_list<T>::Linked_list(): p_list_head{nullptr}, p_list_tail{nullptr}, list_size{0} { // Empty constructor body } Linked_list<T>::~Linked_list() { clear();

8 The Linekd list class Similar for empty() and size():
template <typename T> bool Linked_list<T>::empty() const { return ( nullptr == p_list_head ); } std::size_t Linked_list<T>::size() const { return list_size;

9 The Linekd list class Also for front() and back():
template <typename T> T Linked_list<T>::front() const { if ( empty() ) { std::cerr << "Error: list is empty" << std::endl; throw nullptr; } else { return p_list_head->get_value(); } T Linked_list<T>::back() const { return p_list_tail->get_value();

10 The Linekd list class For find(…), we need to indicate that:
The datum must be of specified templated type The instance of the Node class is of the also is of the same type template <typename T> std::size_t Linked_list<T>::find( T datum ) const { std::size_t position{0}; for ( Node<T> *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;

11 The Linekd list class The print() member function has the same issue with the Node class: template <typename T> void Linked_list<T>::print() const { std::cout << "p_list_head -> "; for ( Node<T> *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;

12 The Linekd list class The push_front(…) member function for a single datum being added has similar requirements: template <typename T> void Linked_list<T>::push_front( T datum ) { p_list_head = new Node<T>{datum, p_list_head}; if ( size() == 0 ) { p_list_tail = p_list_head; } ++list_size;

13 The Linekd list class As does push_back(…):
template <typename T> void Linked_list<T>::push_back( T datum ) { if ( empty() ) { push_front( datum ); } else { assert( size() >= 1 ); p_list_tail->p_next_node = new Node<T>{datum, nullptr}; p_list_tail = p_list_tail->get_next(); ++list_size; }

14 The Linekd list class The push_front(…) for an entire linked list sees no change: template <typename T> void Linked_list<T>::push_front( Linked_list &list ) { if ( !list.empty() ) { list.p_list_tail->p_next_node = p_list_head; p_list_head = list.p_list_head; list_size += list.list_size; list.p_list_head = nullptr; list.p_list_tail = nullptr; list.list_size = 0; }

15 The Linekd list class Neither does push_back(…) for an entire linked list: template <typename T> void Linked_list<T>::push_back( Linked_list &list ) { if ( !list.empty() ) { p_list_tail->p_next_node = list.p_list_head; p_list_tail = list.p_list_tail; list_size += list.list_size; list.p_list_head = nullptr; list.p_list_tail = nullptr; list.list_size = 0; }

16 The Linekd list class The pop_front(…) member function requires a node be temporarily stored: template <typename T> bool Linked_list<T>::pop_front() { if ( empty() ) { return false; } else { assert( size() >= 1 ); Node<T> *p_previous_list_head{p_list_head}; p_list_head = p_list_head->get_next(); delete p_previous_list_head; --list_size; p_list_tail = nullptr; } return true;

17 The Linekd list class Finally, clear() sees no change:
template <typename T> void Linked_list<T>::clear() { while ( !empty() ) { pop_front(); }

18 The Linekd list class Here is a program that tests our class:
int main() { Linked_list<double> list; for ( int i = 0; i < 5; ++i ) { list.push_front( 0.1*i ); } for ( int i = 5; i < 10; ++i ) { list.push_back( 0.1*i ); list.print(); for ( int i = 0; i < 10; ++i ) { double n{0.1*(17*i % 20)}; std::cout << "find(" << n << ") = " << list.find(n) << std::endl; Output: p_list_head -> (0.4) -> (0.3) -> (0.2) -> (0.1) -> (0) -> (0.5) -> (0.6) -> (0.7) -> (0.8) -> (0.9) -> 0 find(0) = 4 find(1.7) = 10 find(1.4) = 10 find(1.1) = 10 find(0.8) = 8 find(0.5) = 5 find(0.2) = 2 find(1.9) = 10 find(1.6) = 10 find(1.3) = 10

19 The Linekd list class Here is a program that tests our class:
for ( int i = 0; i < 8; ++i ) { list.pop_front(); } std::cout << "Size: " << list.size() << std::endl; std::cout << "Empty: " << list.empty() << std::endl; list.print(); return 0; Output: Size: 2 Empty: 0 p_list_head -> (0.8) -> (0.9) -> 0 Size: 0 Empty: 1 p_list_head -> 0

20 Summary Following this lesson, you now
Know how to convert a linked list to a templated class Understand it is always necessary to specify templates for classes other than the one we are using

21 References [1] No references?

22 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.

23 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.


Download ppt "Templated Linked Lists"

Similar presentations


Ads by Google