0% found this document useful (0 votes)
53 views

228 Chapter 5 / Linked Lists: Const Node C

This document summarizes a header file that provides a class for nodes in a linked list and functions for manipulating linked lists. It includes typedefs, constructors, member functions for the node class like set_data() and link(), and notes on const and non-const versions of functions. It also summarizes some functions in the linked list toolkit like list_length() for getting the length of a list.

Uploaded by

Group B
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
53 views

228 Chapter 5 / Linked Lists: Const Node C

This document summarizes a header file that provides a class for nodes in a linked list and functions for manipulating linked lists. It includes typedefs, constructors, member functions for the node class like set_data() and link(), and notes on const and non-const versions of functions. It also summarizes some functions in the linked list toolkit like list_length() for getting the length of a list.

Uploaded by

Group B
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 5

228 Chapter 5 / Linked Lists

pointer c cannot be used to change the node. To be precise, for the declaration
const node *c :
1. You might think that the const keyword prevents c from moving around
and pointing to different nodes. That is wrong. The pointer c can move
and point to many different nodes, but we are forbidden from using c to
change any of those nodes that c points to. (If you should wish to create a
pointer that can be set once during its definition and never changed to
point to a new object, then put the word const after the *. For example:
node *const c = &first; .)
2. Because of the const keyword, you might think that the node that c
points to can never be changed by any means. That’s not quite right either.
Why not? The reason is that we might have another ordinary pointer that
points to the same node that c points to. In that case, the node could be
changed by accessing it through the ordinary pointer. The const keyword
only prevents changing the node by accessing it through c.
3. To enforce the const rule, the C++ compiler permits a pointer such as
c to activate only constant member functions. For example, with our
declaration of c as const node *c , we can activate c->data( ), but
c->set_data( ) is forbidden.
The third rule is a good one, but for applications such as linked lists, the rule of
the C++ compiler doesn’t go quite far enough. We recommend an additional
programming tip that increases reliability:

 PROGRAMMING TIP
A RULE FOR A NODE’S CONSTANT MEMBER FUNCTIONS
A node’s constant member functions should never provide a result that could later
be used to change any part of the linked list. This increases reliability because we
can clearly see which functions have the possibility of causing an alteration to the
underlying data structure.

providing a Our programming tip has a surprising effect: We must sometimes write two
const version similar versions of the same member function. For example, the purpose of the
and a non-const link member function is to obtain a copy of a node’s link field. At first glance,
version of a this sounds like a constant member function, since retrieving a member variable
function does not change an object. We might write this:
node* link( ) const { return link_field; }
WARNING!
This link This implementation does compile, but it violates our programming tip about
implementation constant member functions. For example, suppose we have this list set up:
has a bug!
1.6 3.0
head_ptr NULL
A Fundamental Node Class for Linked Lists 229

Using the constant member function, link, we can execute two statements that
change the data in one of the nodes:
node *second = head_ptr->link( );

After this first statement, we have the following situation:

1.6 3.0
head_ptr NULL
second

The variable second is just an ordinary pointer to a node. It is not a pointer to a


constant node, so we can activate any of its member functions, such as:
second->set_data(9.2);

After this statement, the data in the second node is now 9.2:

1.6 9.2
head_ptr NULL
second

This is a bad situation because the node’s constant member functions should
never provide a result that we can later use to change any part of the linked list.
With this in mind, it makes sense to implement link as a non-constant member
function. Making the function non-constant provides better accuracy about how
the function’s results might be used. So, we will implement link as a non-
constant member function, like this:
node* link( ) { return link_field; }

Unfortunately, this solution has another problem. Suppose that c is a parame-


ter const node *c . We are allowed to activate only the constant member
functions. So, with the non-constant link implementation, we could never acti-
vate c->link( ). The final solution is to provide a second version of the link
member function, implemented this way:
const node* link( ) const { return link_field; }

This second version is a constant member function, so c->link( ) can be used,


even if c is declared with the const keyword. Even though the implementations
of both functions are the same (they both return the link_field), the compiler
converts the link_field to the type const node* for the const version of the
function. Therefore, the return value from the const version of the function can-
not later be used to change any part of the linked list.
254 Chapter 5 / Linked Lists

The implementations of the functions should be placed in a separate imple-


mentation file called node1.cxx. We do not provide a listing of this file, but you
can build it with the implementations from Figures 5.5 through 5.9.
Using the Linked-List Toolkit
The purpose of the node class and its functions is to allow a container class to
store elements on a basic linked list with the simplicity and clarity of using an
array. In addition, having the functions written and thoroughly tested once will
allow us to use the functions to implement many different container classes with
high confidence in their reliability.
So, any programmer can use our node and the toolkit. The programmer
defines the value_type according to his or her need and places the include
directive in the program:
#include "node1.h"
The node class and all the functions (which are in the namespace
main_savitch_5) can then be used to build and manipulate linked lists. This is
what we will do in the rest of the chapter, providing two classes that use the
linked-list toolkit.
Finally, keep in mind that the programmer who uses a class that was built with
the linked-list toolkit does not need to know about the underlying linked lists.

FIGURE 5.10 Header File for the Node Class and the Linked-List Toolkit

A Header File
// FILE: node1.h (part of the namespace main_savitch_5)
// PROVIDES: A class for a node in a linked list and a collection of functions for
// manipulating linked lists
//
// TYPEDEF for the node class:
// Each node of the list contains a piece of data and a pointer to the next node. The
// type of the data is defined as node::value_type in a typedef statement. The value_type
// may be any of the C++ built-in types (int, char, etc.), or a class with a default constructor,
// a copy constructor, an assignment operator, and a test for equality.
//
// CONSTRUCTOR for the node class:
// node(const value_type& init_data, node* init_link)
// Postcondition: The node contains the specified data and link.
// NOTE: The init_data parameter has a default value that is obtained from the default
// constructor of the value_type. In the ANSI/ISO Standard, this notation is also allowed
// for the built-in types, providing a default value of zero. The init_link has a default
// value of NULL. (continued)
A Linked-List Toolkit 255

(FIGURE 5.10 continued)

// NOTE:
// Some of the functions have a return value that is a pointer to a node. Each of these
// functions comes in two versions: a non-const version (where the return value is node* )
// and a const version (where the return value is const node* ).
// EXAMPLES:
// const node *c;
// c->link( ) activates the const version of link
// list_search(c, ... calls the const version of list_search
// node *p;
// p->link( ) activates the non-const version of link
// list_search(p, ... calls the non-const version of list_search
//
// MEMBER FUNCTIONS for the node class:
// void set_data(const value_type& new_data)
// Postcondition: The node now contains the specified new data.
//
// void set_link(node* new_link)
// Postcondition: The node now contains the specified new link.
//
// value_type data( ) const
// Postcondition: The return value is the data from this node.
//
// const node* link( ) const <----- const version
// and
// node* link( ) <----- non-const version
// See the previous note about the const version and non-const versions.
// Postcondition: The return value is the link from this node.
//
// FUNCTIONS in the linked-list toolkit:
// size_t list_length(const node* head_ptr)
// Precondition: head_ptr is the head pointer of a linked list.
// Postcondition: The value returned is the number of nodes in the linked list.
//
// void list_head_insert(node*& head_ptr, const node::value_type& entry)
// Precondition: head_ptr is the head pointer of a linked list.
// Postcondition: A new node containing the given entry has been added at the head of
// the linked list; head_ptr now points to the head of the new, longer linked list.
//
// void list_insert(node* previous_ptr, const node::value_type& entry)
// Precondition: previous_ptr points to a node in a linked list.
// Postcondition: A new node containing the given entry has been added after the node
// that previous_ptr points to.
//
(continued)
256 Chapter 5 / Linked Lists

(FIGURE 5.10 continued)

// const node* list_search


// (const node* head_ptr, const node::value_type& target)
// and
// node* list_search(node* head_ptr, const node::value_type& target)
// See the previous note about the const version and non-const versions.
// Precondition: head_ptr is the head pointer of a linked list.
// Postcondition: The pointer returned points to the first node containing the specified
// target in its data field. If there is no such node, the null pointer is returned.
//
// const node* list_locate(const node* head_ptr, size_t position)
// and
// node* list_locate(node* head_ptr, size_t position)
// See the previous note about the const version and non-const versions.
// Precondition: head_ptr is the head pointer of a linked list, and position > 0.
// Postcondition: The pointer returned points to the node at the specified position in the
// list. (The head node is position 1, the next node is position 2, and so on.) If there is no
// such position, then the null pointer is returned.
//
// void list_head_remove(node*& head_ptr)
// Precondition: head_ptr is the head pointer of a linked list, with at least one node.
// Postcondition: The head node has been removed and returned to the heap;
// head_ptr is now the head pointer of the new, shorter linked list.
//
// void list_remove(node* previous_ptr)
// Precondition: previous_ptr points to a node in a linked list, and this is not the tail node of
// the list.
// Postcondition: The node after previous_ptr has been removed from the linked list.
//
// void list_clear(node*& head_ptr)
// Precondition: head_ptr is the head pointer of a linked list.
// Postcondition: All nodes of the list have been returned to the heap, and the head_ptr is
// now NULL.
//
// void list_copy(const node* source_ptr, node*& head_ptr, node*& tail_ptr)
// Precondition: source_ptr is the head pointer of a linked list.
// Postcondition: head_ptr and tail_ptr are the head and tail pointers for a new list that
// contains the same items as the list pointed to by source_ptr.
//
// DYNAMIC MEMORY usage by the functions:
// If there is insufficient dynamic memory, then the following functions throw bad_alloc:
// the node constructor, list_head_insert, list_insert, list_copy.

(continued)

You might also like