chapter 08-pointers and linked lists
TRANSCRIPT
-
7/30/2019 Chapter 08-Pointers and Linked Lists
1/75
Pointers & Linked ListsChapter 8
-
7/30/2019 Chapter 08-Pointers and Linked Lists
2/75
Run-Time Arrays Intro. to PointersFor declarations like
double doubleVar;char charVar = 'A';
int intVar = 1234;
the compiler constructs the object being declared, which means that it:
1. Allocates memory needed for that type of object
2. Associates the object's name with that memory
3. Initializes that memory
Read (8.4 & 8.5)
1234
A
-
7/30/2019 Chapter 08-Pointers and Linked Lists
3/75
Addresses
& is the address operator in C++
&variable is the address (actual memory location) ofvariable
Example: For the previous scenario:
Values of&intVar, &charVar, and &doubleVal
0x1220, 0x1224, and 0x1225
To make addresses more useful, C++ provides pointer variables.
Definition: Apointer variable (or simplypointer) is a variable whose
value is a memory address.
Declarations:
Type *pointerVariabledeclares a variable namedpointerVariablethat can store the address of an object of type Type.
-
7/30/2019 Chapter 08-Pointers and Linked Lists
4/75
#include using namespace std;
int main(){int i = 11, j = 22;double d = 3.3, e = 4.4;
// pointer variables that:// store addresses of ints
Output produced:&i = 0x7fffb7f4&j = 0x7fffb7f0&d = 0x7fffb7e8
&e = 0x7fffb7e0
int * iptr, * jptr;
double * dptr, * eptr;
iptr = &i;jptr = &j; // value of iptr is address of i// value of jptr is address of j
dptr = &d; // value of dptr is address of deptr = &e; // value of eptr is address of e
cout
-
7/30/2019 Chapter 08-Pointers and Linked Lists
5/75
Dereferencing* is the dereferencing (or indirection) operator
It can be used to access the value stored in a location.For an expression of the form
*pointerVariable
the value produced is not the addressstored in
pointerVariablebut is insteadthe value stored in memory at that address.
Value ofdptr: 0x7fffb7e8
3.3
*dptr
We saydptrpoints to that memory location
(whose address is0x7fffb7e8)
Value of*dptr: 3.3
A dereferenced pointer is a
variable and can thus be
used in the same way as
all variables of the type to
which the pointer is b
ound
-
7/30/2019 Chapter 08-Pointers and Linked Lists
6/75
Suppose we replace the preceding output statements by:cout
-
7/30/2019 Chapter 08-Pointers and Linked Lists
7/75
Recall the C++ function to exchange the values of two int variables:
void Swap(int & a, int & b){ int temp = a; a = b; b = temp; }
The values of two int variables x and ycan be exchanged with the call:
Swap(x,y);
The first C++ compilers were just preprocessors that read a C++ program,
produced functionally equivalent C code, and ran it through the C compiler. ButC has no reference parameters. How were they handled?
Translate the function to
void Swap(int * a, int *b)
{ int temp = *a; *a = *b; *b = temp; }and the preceding call to: Swap(&x, &y);
This indicates how the call-by-reference parameter mechanism works:
A reference parameter is a variable containing the
address of its argument (i.e., it's a pointer variable)
and that is automatically dereferenced when used.
Parameter
Argument
A Note About Reference Parameters:
-
7/30/2019 Chapter 08-Pointers and Linked Lists
8/75
Other uses of Pointers
Command-line arguments are passed to a mainfunction main() via two parameters:
argc (the argument count): an int whose value
is the number of strings on the command line
argv (the argument vector): an array of pointersto charsargv[i] is the address of the ith
character string on the command line
Value of a function name is the starting address ofthat function i.e., a function is a pointer!
One fxn can be passed to another as an argument
-
7/30/2019 Chapter 08-Pointers and Linked Lists
9/75
Anonymous variablesDefinitions:
A variable is a memory location.
A named variable has a name associated with its memory
location, so that this memory location can be accessed
conveniently.
If*ptrVar points to a memory location that already has a
name associated with it, we can think of*ptrVar as an
alias or synonym for this location
An anonymous variable has no name associated with its
memory location.
If the address of that memory location is stored in a pointer
variable, then the variable can be accessed indirectly usingthe pointer.
-
7/30/2019 Chapter 08-Pointers and Linked Lists
10/75
Named variables are created using a normal variable declaration.
For example, the declaration
int j = 22;
i. constructed an integer (4-byte) variable at memory address
0x7fffb7f0 and initialized those 4 bytes to the value 22; and
ii. associated the name j with that address, so that allsubsequent uses ofj refer to address 0x7fffb7f0 ; the
statement
cout
-
7/30/2019 Chapter 08-Pointers and Linked Lists
11/75
Dynamic AllocationAnonymous variables are usually created using the
new operator, whose form is:
new Type
When executed, this expression:
i. allocates a block of memory big enough for an object oftype Type,
and
ii. returns the starting address of that block of memory.
Type * ptr; ptr
ptr = new Type;ptr MemoryforType
value
?
-
7/30/2019 Chapter 08-Pointers and Linked Lists
12/75
#include using namespace std;
int main(){double * dptr,
* eptr;dptr = new double;eptr = new double;cout > *dptr >> *eptr;cout
-
7/30/2019 Chapter 08-Pointers and Linked Lists
13/75
This program uses the new operator to allocate two anonymousvariables whose addresses are stored inpointer variablesdptrand
eptr:
Note 1: We could have performed these allocations as initializations
in the declarations ofdptr and eptr:
double * dptr = new double,* eptr = new double;
anonymous variablesdptr
eptr
dptr
eptr
2.2
3.3
The input values are then stored in these indirectly via the
pointers dptr and eptr:
*dptr
*eptr
Note 1
-
7/30/2019 Chapter 08-Pointers and Linked Lists
14/75
Note 2: newmust be used each time a memory allocation is needed.
double *dptr, *eptr;dptr = eptr = new double;
eptr = new doubleallocates memory for a double and assigns its
address toeptr.
dptr = eptrsimply assigns this same address to dptr; it does not
allocate new memory.
*dptr = 3.14159;
*eptr = 0.1423;cout
-
7/30/2019 Chapter 08-Pointers and Linked Lists
15/75
Note 3: What if we changed this to:
double *dptr, *eptr;dptr = new double;
*dptr = 3.14159;*eptr = 0.1423;
The first assignment is okay and stores 3.14159 in the memory location pointedto by eptr.
However, the second results in the most dreadedof all errors:
An attempt to dereference an undefined pointer variable (i.e., one to
which no memory address has been assigned) produces
asegmentation fault.
Note 4: It is an error to attempt to allocate the wrong type of memory block to
a pointer variable; for example,double dptr = new int; // error
produces a compiler error.
Notes 3 & 4
-
7/30/2019 Chapter 08-Pointers and Linked Lists
16/75
Run-time arraysRecall that arrays as we know them have their capacities fixed at compile time.
For example, array a declared bydouble a[50];
has exactly 50 elements.
This is adequate if a fixed-capacity array can be used to store all of the data sets
being processed. However, this is often not true because the sizes of data sets
vary. In this case, we must either:
Make array's capacity large enough to handle biggest data
setan obvious waste of memory for smaller data sets.
or
Change capacity in array's declaration in source code and recompile
(yuck!).
It would be nice if the user could specify the capacity of the array at
run time and an array of that capacity would then be allocated and used. This is
possible in C++.
All ti A D i R Ti
-
7/30/2019 Chapter 08-Pointers and Linked Lists
17/75
The operator new can be used in an expression of the form
new Type[n]
where n is an integer expression, to allocate an array with n elements, eachof type Type; it returns the base address of that array.
This allocation occurs when this expression is executed, that is, at
run-time, not at compile-time. This means that the user
can input a capacity, and the program can allocate an array withexactly that many elements!
n-1
Allocating an Array During Run-Time:
new gets memory from the heap (as opposed to the stack, which holds global
variables, activation records for each function, etc. for that program). Thisis the main difference between just saying array[n] and using this
dynamic allocation (also passing of multidimensional arrays). new replacesfree,malloc, and calloc in C.
Dynam c Array Alloca on
-
7/30/2019 Chapter 08-Pointers and Linked Lists
18/75
The address returned by new must be assigned to a pointer of type Type.
So a declaration of a run-time-allocated array is simply a pointer declaration:
Type * arrayPtr;
int numItems;double dub[20]; // an ordinary compile-time arraydouble *dubPtr; // a pointer to a (run-time) array
cout > numItems;
dubPtr = new double[numItems];
Recall: The value of an ordinary array like dub is the base address of the array.So, in a subscript expression like
dub[i] ( same as operator[](dub, i))
the subscript operator actually takes two operands: the base address of the arrayand an integer index. Since pointer variable dubPtr also is the base address of
an array, it can be used in the same manner as an array name:dubPtr[i] ( same as operator[](dubPtr, i))
Example: for (int i = 0; i < numItems; i++)
cout
-
7/30/2019 Chapter 08-Pointers and Linked Lists
19/75
Memory Allo-/Deallo-cation
new receives its memory allocation from pool
of available memory called the heap orfreestore. It is usually located between a program
and its run-time stack.
Programstatements
Run-Time
Stack
HeapThe run-time stack grows each time a function is
called, so it is possible for it to overun the heap
(ifmain() calls a function that calls a functionthat calls a function ... e.g., due to infinite or too
deeply nested recursion) It is also possible for
the heap to overun the run-time stack due to toomany (or too large) new operations.
Ch ki f N ll
-
7/30/2019 Chapter 08-Pointers and Linked Lists
20/75
When the heap has been exhausted, newreturns the value 0 (called thenull address or null pointer).
Common to picture a null pointer variable using the electrical ground symbol:
Attempting to dereference a null (or uninitialized or void) pointer variable
produces asegmentation fault.
So check whether a pointer is null before attempting to dereference it.
double *dptr = new double;if (dptr == 0) // check if pointer has null value
{cerr
-
7/30/2019 Chapter 08-Pointers and Linked Lists
21/75
delete operatorRun-time stackgrows each time a function is called, and shrinks
again when that function terminates.Need an analogous method to reclaim memory allocated bynew, i.e.
shrink the heap when an anonymous variable is no longer needed.
Otherwise a memory leak (memory allocated but not usable) results.
For this, C++ provides the delete operation:
deletepointerVariable;
which deallocates the block of memorywhose address is stored inpointerVariable
D l t i A P i t
-
7/30/2019 Chapter 08-Pointers and Linked Lists
22/75
For run-time arrays, to return to the heap memory allocated to array pointed to
by arrayPtr. use the delete operator in the form
delete[] arrayPtr;
Important to do this because memory leaks involving arrays can result in
considerable loss of memory.
For example:for(;;){int n;cout > n;if (n == 0) break;double * arrayPtr = new double[n];// process arrayPtr
. . .}
Each new allocation of memory to arrayPtrmaroons old memory block
Deleteing Array Pointers
d f Cl Obj t
-
7/30/2019 Chapter 08-Pointers and Linked Lists
23/75
int * ptr1 = new int; // integer allocated*ptr1 = 103; // anonymous integer initialized
int * ptr2; // no integer allocated
ptr2 = new int(104); // anonymous integer allocated// and initialized
IfType is a class, new Typewill
i. Allocate memoryii. Call Type's constructor to create a value
to use to initialize this memory block.
new can also be used in the formnew Type(initVal)
to call an explicit-value constructor.
IfType is a class, delete Typewill
i.
ii. Deallocate the memory
Call Type's destructor to destroy the object
in this memory block.
new and deletefor Class Objects
-
7/30/2019 Chapter 08-Pointers and Linked Lists
24/75
Run-time Allo-/Deallo-cation in a Class
Classes that use run-time allocated storage require some newfunction members and modifications of others:
1.Destructors: To "tear down" the storage structure and
deallocate its memory.
2.Copy constructors: To make copies of objects
(e.g., value parameters)
3.Assignment: To assign one storage structure to another.
We will illustrate these using our Stack class.
D t M b
-
7/30/2019 Chapter 08-Pointers and Linked Lists
25/75
We will use a run-time allocated array so that the user can specify the capacity ofthe stack during run time. We simply change the declaration of themyArraymember to a pointer and STACK_CAPACITY to a variable; to avoid confusion,
we will use different names for the data members.
//***** RTStack.h *****. . .
template class Stack{/***** Function Members *****/public:
. . .
/***** Data Members*****/private:int myCapacity_, // capacity of stack
myTop_; // top of stackStackElement * myArrayPtr; // run-time array to store elements
};
Data Members
-
7/30/2019 Chapter 08-Pointers and Linked Lists
26/75
Want to permit declarations such asStack s1, s2(n);
to construct s1 as a stack with some default capacity,to construct s2 as a stack with capacity n.
To permit both forms, we use a constructor with a default argument.
/* --- Class constructor ---Precondition:A stack has been defined.Receive: IntegernumElements>0;(default=128)Postcondition: stack constructed with capacity
numElements
*/
Stack(int numElements = 128);
This constructor must really construct something
(and not just initialize data members):
Class Constructors
xamp e
-
7/30/2019 Chapter 08-Pointers and Linked Lists
27/75
template Stack::Stack(int numElements){
assert (numElements > 0); // check preconditionmyCapacity_ = numElements; // set stack capacity
// allocate array of this capacitymyArrayPtr = new StackElement[myCapacity_];
if (myArrayPtr == 0) // memory available?
{cerr > num;Stack s1, s2(num);
s1 will be constructed as a stack with capacity 128 ands2 will be constructed as a stack with capacity num.
xamp e
Other stack operations
-
7/30/2019 Chapter 08-Pointers and Linked Lists
28/75
Other stack operations: empty, push, top, pop, output
The prototype and definition ofempty() as well as the prototypes ofpush(),
top(),pop(), and operator
-
7/30/2019 Chapter 08-Pointers and Linked Lists
29/75
For any class object obj we have used up to now, when obj is declared, theclass constructor is called to initialize obj. When the lifetime ofobj is over,
its storage is reclaimed automatically because the location of the memory
allocated is determined at compile-time.
For objects created during run-time, however, a new problem arises. To
illustrate, consider a declaration
Stack st(num);
The compiler knows the data membersmyCapacity_,myTop_, andmyArrayPtrofst so it can allocate memory for them:
myArrayPtr
myTop_
myCapacity_st
Array to store stack elements is created by the constructor; somemory for it isn't allocated until run-time:
myArrayPtr
myTop_
myCapacity_st
0 1 2 3 4 num-1
Class Destructor
Marooned Memory
-
7/30/2019 Chapter 08-Pointers and Linked Lists
30/75
When the lifetime ofst ends, the memory allocated tomyCapacity_,myTop_, andmyArrayPtr is automatically reclaimed, but not for the run-time
allocated array:
Marooned!
We must add a destructor member function to the class to avoid this memory
leak.
Destructor's role: Deallocate memory allocated at run-time
(the opposite of the constructor's role).
At any point in a program where an object goes out of scope,
the compiler inserts a call to this destructor.
That is:
When an object's lifetime is over,
its destructor is called first.
0 1 2 3 4 . . . num-1
Marooned Memory
estructor
-
7/30/2019 Chapter 08-Pointers and Linked Lists
31/75
Form of destructor:
Name is the class name preceded by a tilde (~).
It has no arguments or return type.
For our Stack class, we use the delete operation to deallocate the run-time
array.
/* --- Class destructor ---Precondition: Lifetime of Stack containing this
function should end.Postcondition: The run-time array in the Stack containing
this function has been deallocated.--------------------------------------------------------*/
~Stack();
// Following class declaration// Definition of destructor
template inline Stack::~Stack(){delete[] myArrayPtr;
}
estructor
Destructor Memory Reclamation
-
7/30/2019 Chapter 08-Pointers and Linked Lists
32/75
Suppose st is
When st's lifetime is over, st.~Stack() will be called first,which produces
Memory allocated to stmyCapacity_,myTop_, andmyaArrayptrwill then be reclaimed in the usual manner.
myArrayPtr
myTop_
myCapacity_st
0 1 2 3 4a b c
5
2
myArrayPtr
myTop_
myCapacity_st
5
2
Destructor Memory Reclamation
C C C
-
7/30/2019 Chapter 08-Pointers and Linked Lists
33/75
Class Copy Constructor
Is needed whenever a copy of a class object must be built,
which occurs:
When a class object is passed as a value parameter
When a function returns a class object
Iftemporary storage of a class object is needed
In initializations
If a class has no copy constructor, the compiler uses adefaultcopyconstructor that does a byte-by-byte copy of the object.
This has been adequate for classes without dynamically allocated data, but is
not adequate for classes containing pointers to run-time allocated arrays (or
other structures) . It gives rise to the aliasing problem.
Class Copy Constructor
Byte-by-Byte copying undesirable with dynamic memory
-
7/30/2019 Chapter 08-Pointers and Linked Lists
34/75
Example: A byte-by-byte copying ofst to produce a copy stCopy gives
Not correctcopies ofmyCapacity_,myTop_, andmyArrayPtr weremade, but not a copy of the run-time allocated array. Modifying stCopy willmodify st also! Need to create a distinct copy ofst, in which the array instCopy has exactly the same elements as the array in st:
0 1 2 3 4
a b cmyArrayPtr
myTop_
myCapacity_st
5
2
stCopy
myArrayPtr
myTop_
myCapacity_ 5
2
myArrayPtr
myTop_
myCapacity_st
5
2 0 1 2 3 4a b c
stCopy
myArrayPtr
myTop_
myCapacity_ 5
2 0 1 2 3 4a b c
Byte by Byte copying undesirable with dynamic memory
Copy Constructor Form
-
7/30/2019 Chapter 08-Pointers and Linked Lists
35/75
Form of copy constructor:
It is a constructorso it must be a function member, its name is the class name,
and it has no return type. It needs a single parameter (source of copy) whose type is
the class; this must be a reference parameter and should be
const since it does not change this parameter or pass information
back through it.
/* --- Copy Constructor ---
* Precondition: A copy of a stack is needed* Receive: The stack to be copied (as a const* reference parameter)* Postcondition: A copy of original has been constructed.
************************************************************/
Stack(const Stack & original);
(Otherwise it would be a value parameter, and since a value parameter is a copyof its argument, a call to the copy instructor will try and copy its argument, which
calls the copy constructor, which will try and copy its argument, which calls the
copy constructor . . . )
Copy Constructor Form
Definition of the Copy Constructor
-
7/30/2019 Chapter 08-Pointers and Linked Lists
36/75
template Stack::Stack(const Stack & original){
myCapacity_ = original.myCapacity_; // copy myCapacity_ membermyTop_ = original.myTop_ ; // copy myTop_ member
myArrayPtr = new StackElement[myCapacity_];// allocate array in copy
if (myArrayPtr == 0) // check if memory available{cerr
-
7/30/2019 Chapter 08-Pointers and Linked Lists
37/75
Another operation that requires special attention for classes containing pointers to run-
time arrays (or other structures). Like the copy constructor, the default assignment
operation does byte-by-byte copying. With it, the assignment statement
s2Copy = s2;
will yield aliases as before; themyArrayPtr data members of both s2 and s2Copywill both point to the same anonymous array.
Need to overload the assignment operator (operator=) so that it creates a distinct
copy of the stack being assigned.
operator=must be a member function. So an assignmentstLeft = stRight;
will be translated by the compiler asstLeft.operator=(stRight);
ss gnment perator
ro o ype
-
7/30/2019 Chapter 08-Pointers and Linked Lists
38/75
/* --- Assignment Operator ---
* Receive: Stack stRight (the right side of the assignment* operator* Postcondition: The Stack will be a copy of stRight* Return: A reference to the current Stack************************************************************/
operator=
(const Stack & original);
The return type is a reference to a Stack since operator=() mustreturn the object on the left side of the assignment and not a copy of it (to
make chaining possible).
Stack &
ro o ype
Definition of operator=
-
7/30/2019 Chapter 08-Pointers and Linked Lists
39/75
It is quite similar to that for the copy constructor, but there are some differences:
1. Object on the left side of the assignment may already have a value. Mustdestroy old valuedeallocate the old so no memory leak
and allocate a new one.
2. Assignment must be concerned withself-assignments: st = st;.Can't destroy the old value in this case.
3. operator=() must return the Stack containing this function.
For #3 we use the following property of classes:
Every member function of a class has access to a (hidden) pointer constantthiswhose value is the address of the object containing this function.
The expression*this
refers to the object itself.
Definition of operator=
Example
-
7/30/2019 Chapter 08-Pointers and Linked Lists
40/75
template Stack & Stack::operator=
(const Stack & original)
{if ( ) // check that not st = st{delete[] myArrayPtr; // destroy previous array
myArrayPtr = new StackElement[myCapacity_];
if (myArrayPtr == 0) // check if memory available{cerr
-
7/30/2019 Chapter 08-Pointers and Linked Lists
41/75
//***** Test Driver ***********#include using namespace std;#include "RTStack.h"
Print (Stack st){cout Size;
Stack S(Size);for (int i = 1; i 0'
Abort
Test Driver
Statements added in
the constructor,
copy constructor,
and destructor to
trace when they
are called
ummary o o n ers
-
7/30/2019 Chapter 08-Pointers and Linked Lists
42/75
ummary o o n ers A variable is made of:
a memory address
a name
a value A pointer is a special variable that can only hold an addressas its value
You can get the addressof any variable using the & (address-of) operator The pointer is said to point tothe value at the memory address it holds as its value
Use the * (dereference) operator to get the value at that address
A pointer can point to another variable (as an aliasorsynonym) or it can point toa dynamically allocated (anonymous) variable in heapmemory
Use new to get new memory from the heap Use delete to release the memory back to the heap You can allocate memory for an individual variable or an array
An array is a special constant pointerthat holds the base addressof the array(the address of the first element) Use new Type[n] to allocate enough memory from the heap for an array of type Type with
n number of elements
Use delete [] to release the memory for the dynamic array back to the heap Use the [] to access the individual elements of an array pointer (just like a regular array)
If your class uses dynamic memory allocation, you must provide your ownversion of: A destructor
A copy constructor
The assignment operator
See http://computer.howstuffworks.com/c12.htm
Read (8.1 & 8.2)
http://computer.howstuffworks.com/c12.htmhttp://computer.howstuffworks.com/c12.htm -
7/30/2019 Chapter 08-Pointers and Linked Lists
43/75
Part II: Linked Lists
As an abstract data type,a list is a finite sequence (possibly empty) of elements with basic
operations that vary from one application to another.
Basic operations commonly include:
Construction: Allocate and initialize a list object (usually empty)
Empty: Check if list is empty
Insert: Add an item to the list at any point
Delete: Remove an item from the list at any point
Traverse: Go through the list or a part of it, accessing and
processing the elements in the order they arestored
Array/Vector-based Implementation
-
7/30/2019 Chapter 08-Pointers and Linked Lists
44/75
Array/Vector-Based Implementation of a List:
Data Members: Store the list items in consecutive array or vector
locations:a1, a2, a3 , . . . an
a[0] a[1] a[2] ... a[n-1] a[n] ... a[CAPACITY-1]
For an array, add amySize member to store the length (n) of the list.
Basic Operations
Construction: SetmySize to 0;if run-time array, allocate memory for itFor
vector: let its constructor do the work
Empty: mySize == 0For vector: Use its empty() operation
y p
Operations
-
7/30/2019 Chapter 08-Pointers and Linked Lists
45/75
Traverse:for (int i = 0; or
i < size; i++){ Process(a[i]); }
Insert: Insert 6 after 5 in 3, 5, 8, 9, 10, 12, 13, 15
3, 5, 6, 8, 9, 10, 12, 13, 15
Have to shift array elements to make room.
Delete: Delete 5 from 3, 5, 6. 8, 9, 10, 12, 13, 15
3, 6, 8, 9, 10, 12, 13, 15
Have to shift array elements to close the gap.
This implementation of lists is inefficient for dynamic lists (those that change
frequently due to insertions and deletions), so we look for an alternative
implementation.
i = 0;while (i < size){ Process(a[i]); i++; }
p
Linked Lists (8 2)
-
7/30/2019 Chapter 08-Pointers and Linked Lists
46/75
Linked Lists (8.2)Minimal requirements:
1. Locate the first element2. Given the location of any list element, find its successor
3. Determine if at the end of the list
For the array/vector-based implementation:
1. First element is at location 0
2. Successor of item at location i is at location i + 13. End is at location size1
A gross inefficiency is caused by #2insertions and deletions requires shifting
elements.
Fix: Remove requirement that list elements be stored inconsecutive locations.
But then need a "link" that connects each element to its
successor
linked lists
Nodes: Data & Next
-
7/30/2019 Chapter 08-Pointers and Linked Lists
47/75
Nodes: Data & Next
9
data
next
9 17 22 26 34firstdata
next
A linked list is an ordered collection of elements called nodes each of which has
two parts:
(1) Data part: Stores an element of the list
(2) Next part: Stores a link (pointer) to the next list element.
If there is no next element, a special null value is used.
Additionally, an external link must be maintained that points to the location
of the node storing the first list element.
This value will be null if the list is empty.
Example: A linked list storing 9, 17, 22, 26, 34:
9
data
next
Basic Operations
-
7/30/2019 Chapter 08-Pointers and Linked Lists
48/75
Basic Operations
Basic Operations:
Construction: first = null_value first
Empty: first == null_value?
Traverse:
ptr = first;while (ptr != null_value){
Process data part of node pointed to byptrptr = next part of node pointed to byptr;
}
See pp. 391-2
xamp e
-
7/30/2019 Chapter 08-Pointers and Linked Lists
49/75
9 17 22 26 34first
ptr
9 17 22 26 34first
ptr
.
.
.
9 17 22 26 34first
ptr
9 17 22 26 34first
ptr
ptr = first;while (ptr != null_value){Process data part of
node pointed to byptr;
ptr = next part of nodepointed to byptr;
}
xamp e
nser
-
7/30/2019 Chapter 08-Pointers and Linked Lists
50/75
nserInsert: To insert 20 after 17 in the preceding linked list
need address of item before point of insertionpredptr points to the node containing 17
(2) Set the next pointer of this new node equal to the next pointer in its
predecessor, thus making it point to its successor.
9 17 22 29 34
predptr
first
20
9 17 22 29 34
predptr
newptr
first
20
9 17 22 29 34
predptr
newptr
first
(1) Get a new node pointed to by newptr and store 20 in it
predptr = pointer to
predecessor
on(3) Reset the next pointer of its predecessor to point to this new node
-
7/30/2019 Chapter 08-Pointers and Linked Lists
51/75
on .(3) Reset the next pointer of its predecessor to point to this new node.
20
9 17 22 29 34
predptr
newptr
first
Note that this also works at the end of the list.Example: Insert a node containing 55 at the end of the list.
(1) as before(2) as beforesets next link to null pointer(3) as before
9 17 22 29 34first 20
55
predptr
newptr
9 17 22 29 34first 20
55
predptr
newptr
9 17 22 29 34first 20
55
predptr
newptr
Insert at beginning
-
7/30/2019 Chapter 08-Pointers and Linked Lists
52/75
Insert at beginning
Inserting at the beginning of the list requires a modification ofsteps 2 and 3:
Example: Insert a node containing 5 at the beginning of the list.
(1) as before
(2) set next link to first node in the list(3) set first to point to new node.
Note: In all cases, no shifting of list elements is required !An O(1) operation!
9 17 22 29 55first 20
redptr
349 17 22 29 55first 20
5
redptr
newptr
349 17 22 29 55first 20
5
redptr
newptr
349 17 22 29 55first 20
5
redptr
newptr
34
e e on
-
7/30/2019 Chapter 08-Pointers and Linked Lists
53/75
e e onDelete: Delete node containing 22 from following list. Supposeptr points to thenode to be deleted andpredptr points to its predecessor (the node containing 20)
(1) Do a bypass operation: Set the next pointer in the predecessor to
point to the successor of the node to be deleted
(2) Deallocate the node being deleted.
5 17 22 29 34first 209
predptr ptr
5 17 22 29 34first 209
predptr ptr
5 17 22 29 34first 20
free store
9
predptr ptr
eg nn ng en
-
7/30/2019 Chapter 08-Pointers and Linked Lists
54/75
eg nn ng enSame process works at the end of the list.
Example: Delete the node at the end of the list.
(1) as beforesets next link to null pointer
(2) as before
Deleting at the beginning of the list requires a modification of step 1:
Example: Delete 5 from the previous list
(1) reset first
(2) as before
5 17 22 29first 9
predptr ptr
345 17 22 29first 9
predptr ptr
34
5 17 22 29first 9
predptr ptr
5 17 22 29first 9
predptr ptr
5 17 22 29first 9
free storepredptr ptr
5 17 22 29first 9
predptr ptr
34
free store
Note again that in all cases, no shifting of list elements is required !
An O(1) operation!
Pros & Cons
-
7/30/2019 Chapter 08-Pointers and Linked Lists
55/75
Pros & Cons
Advantanges of linked lists:
Access any item as long as external link to first item maintained
Insert new item without shifting
Delete existing item without shifting
Can expand/contract as necessary
Disadvantages
Overhead of links: used only internally, pure overhead
Pointers require extra space and processor requirements
If dynamic, must provide destructor, copy constructor
No longer have direct access to each element of the list
O(1) access becomes O(n) access since we must go through first
element, and then second, and then third, etc. Sorting
expensive!
ne c en
-
7/30/2019 Chapter 08-Pointers and Linked Lists
56/75
List-processing algorithms that require fast access to each element cannot
(usually) be done as efficiently with linked lists.
Examples: Appending a value at the end of the list:
Array-based method:a[size++] = value;
or for a vector:
v.push_back(value);
For a linked list:
Get a new node; set data part = value and next part = null_value
If list is empty
Set first to point to new node.
ElseTraverse list to find last node
Set next part of last node to point to new node.
Other examples:
Many sorting algorithms need direct access
Binary search needs direct access
ne c en
Implementing Linked Lists
-
7/30/2019 Chapter 08-Pointers and Linked Lists
57/75
Implementing Linked Lists
Can be done in various ways. For example, we could use arrays/vectors
(Read 8.3)
For nodes:
typedef int DataType; // type of list elements
typedef int Pointer; // pointers are array indicesstruct NodeType{DataType data;Pointer next;
};
or ree s ore:
-
7/30/2019 Chapter 08-Pointers and Linked Lists
58/75
const int NULL_VALUE = -1;
const int numberOfNodes = 2048;
NodeType node[numberOfNodes];Pointer free; // points to a free node
// Initialize free store// Each node points to the next onefor (int i = 0; i < numberOfNodes - 1; i++)node[i].next = i + 1;
node[numberOfNodes - 1].next = NULL_VALUE;free = 0;
0
123...
numNodes-1
. . .
data next
1
23
4
-1
numNodes-1
nodefree
0
or ree s ore:
xamp e
-
7/30/2019 Chapter 08-Pointers and Linked Lists
59/75
// Maintain free store as a stack// New operationPointer New(){ Pointer p = free;if (free != NULL_VALUE)free = node[free].next;
elsecerr
-
7/30/2019 Chapter 08-Pointers and Linked Lists
60/75
For the linked list operations:
Use node[p].data to access the data part of node pointed to byp
Use node[p].next to access the next part of node pointed to byp
Example: Traversal
Pointer p = first;
while (p != NULL_VALUE){Process(node[p].data);
p = node[p].next;}
perat ons
-
7/30/2019 Chapter 08-Pointers and Linked Lists
61/75
Using C++ Pointers and Classes (8.6)
To Implement Nodes
class Node{public:
DataType data;
Node * next;};
Note: The definition of aNode is arecursive (or self-referential)definition because it uses the nameNode in its definition:
the next member is defined as a pointer to aNode .
Pointers and Nodes
-
7/30/2019 Chapter 08-Pointers and Linked Lists
62/75
How do we declare pointers, assign them, access contents of nodes, etc.?
Declarations:
Node * ptr; or typedef Node * NodePointer;NodePointer ptr;
Allocate and Deallocate:
ptr = new Node; delete ptr;
To access the data and next part of node:
(*ptr).data and (*ptr).next
or better, use the ->operator:
ptr->data and ptr->next
Pointers and Nodes
y pu c o es
-
7/30/2019 Chapter 08-Pointers and Linked Lists
63/75
y pu c o esWhy make data members public in class Node?
This class declaration will be placed inside another class declaration forLinkedList. The data members data and next of structNode will be
public inside the class and thus will accessible to the member and friend functionsof the class, but they will be private outside the class.
#ifndef LINKEDLIST#define LINKEDLISTtemplate
class LinkedList{private:class Node{
public:
DataType data;Node * next;};typedef Node * NodePointer;. . .
};
#endif
So why not just makeNode a
struct? We could, but it is
common practice to use structfor C-style structs that contain
no functions (and we will wantto add a few to ourNodeclass.)
Simple Linked Lists
-
7/30/2019 Chapter 08-Pointers and Linked Lists
64/75
Simple Linked ListsData Members forLinkedList:
Linked lists like
9 17 22 26 34first
are characterized by:
(1) There is a pointer to the first node in the list.(2) Each node contains a pointer to the next node in the list.
(3) The last node contains a null pointer.
We will call the kind of linked lists we've just considered simple linked lists to
distinguish them from other variations we will consider shortlycircular,
doubly-linked, lists with head nodes, etc..
For simple linked lists, only one data member is needed: a pointer to the first
node. But, for convenience, another data member is usually added that keeps a
count of the elements of the list:
To skip element-counting
-
7/30/2019 Chapter 08-Pointers and Linked Lists
65/75
L
first
mySize 5
9 17 22 26 34
Otherwise we would have to traverse the list and count the elementseach time we need to know the list's length.
(See p. 446)
1. Set count to 0.2. Makeptr point at the first node.
3. Whileptr is not null:a. Increment count .b. Makeptr point at the next node.
4. Return count .
To skip element counting
unct on em ers
-
7/30/2019 Chapter 08-Pointers and Linked Lists
66/75
Function Members forLinkedList:
Constructor: Make first a null pointer and setmySize to 0.
Insert, Delete
Destructor: Why is one needed? For the same reason as for run-time arrays.
If we don't provide one, the default destructor used by the compiler for a linked list
like that above will result in:
L
firstmySize 5
9 17 22 26 34
free store
marooned!
L
firstmySize 5
9 17 22 26 34
unct on em ers
Copy Constructor
-
7/30/2019 Chapter 08-Pointers and Linked Lists
67/75
Copy constructor: Why is one needed? For the same reason as for
run-time arrays.
If we don't provide one, the default copy constructor (which just does a byte-by-byte copy) used by the compiler for a linked list like L will produce:
L
firstmySize 5
9 17 22 26 34
copyOfL
first
mySize 5
L
firstmySize 5
9 17 22 26 34
Copy Constructor
The STL list Class Template
-
7/30/2019 Chapter 08-Pointers and Linked Lists
68/75
It is implemented as a circular doubly-linked list with
head node.
L
first
mySize 5
last17 22 26 349
prev
next
data
Its node structure is: struct list_node{pointernext,
prev;T data;
}
listis a sequential container that is optimized for
insertion and erasure at arbitrary points in the sequence.
FromSTL's
doc.
The STL list T Class Template
Allo/deallo-cation in list
-
7/30/2019 Chapter 08-Pointers and Linked Lists
69/75
On the surface, listlooks quite simple. But it's allo/deallo-cation scheme ismore complex than simply using new and delete operations.
To reduce the inefficiency of using the heap manager for large numbers of
allo/deallo-cations, it does it's own memory management.
Basically, for each list of a certain type T:
When a node is needed:
1. If there is a node on the free list, allocate it.
(This is maintained as a linked stack in exactly the way wedescribed earlier.)
2. If the free list is empty:
a. Call the systems heap manager to allocate a block of memory (called
a buffer)typical size: 4K bytes.
b. Carve it up into pieces of size required for a node of a list.When a node is deallocated:Push it onto the free list.
Whenalllists of this type T have been destroyed:
Return all buffers to the heap.
st< > vs ot er conta ners
-
7/30/2019 Chapter 08-Pointers and Linked Lists
70/75
Comparing listwith other containers:
Note that listdoes not support direct access and thusdoes not have the subscript operator [].
Property Array vector deque list
Direct/random access ([]) X
Sequential access
Insert/delete at front - - + +
Insert/delete in middle - - - +
Insert/delete at end + + + +
Overhead lowest low low/medium high
st s ot e co ta e s
list Iterators
-
7/30/2019 Chapter 08-Pointers and Linked Lists
71/75
listiterators:
list's iterator is "weaker" than that for vector.
vector: random access iterators
list: bidirectionaliterators
They have the following operations in common:
++ Move iterator to next element (likeptr = ptr-> next)-- Move iterator to preceding element (likeptr = ptr-> prev)
* dereferencing operator (likeptr-> data)
= assignment (for same type iterators)
it1 = it2 makes it1 positioned at same element as it2== and != (for same type iterators)
checks whether iterators are positioned at the same element
E l C t t li t t i i fi t 4 i txamp e
-
7/30/2019 Chapter 08-Pointers and Linked Lists
72/75
Example: Construct a list containing first 4 even integers;
then output the list.
list l;
for (int i = 1; i
-
7/30/2019 Chapter 08-Pointers and Linked Lists
73/75
Function Member Description
Constructorslistl;
listl(n);
listl(n, initVal);
listl(fPtr, lPtr);
Copy constructor
Constructl as an emptylist
Construct
l as alistto contain n elements (set to
default value)
Constructl as alistto containn copies ofinitVal
Constructl as alistto contain copies of elements in
memory locationsfptrup tolptr (pointers of typeT*)
Destructor~list()
Destroy contents, erasing all items.
l.empty()
l.size()Returntrueif and only ifl contains no values
Return the number of values lcontains
l.push_back(value);l.push_front(value);l.insert(pos, value)
l.insert(pos, n, value);
l.insert(pos,fPtr, lPtr);
Appendvalueatl's end
Insertvalue in front ofl's first element
Insertvalueintolat iterator positionposand return an
iterator pointing to the new element's position
Insertncopies ofvalueintolat iterator positionpos
Insertcopies of all the elements in the range [fPtr, lPtr)
at iterator position
pos
unc on em ers con .
-
7/30/2019 Chapter 08-Pointers and Linked Lists
74/75
l.pop_back();
l.pop_front();
l.erase(pos);l.erase(pos1,pos2);
l.remove(value);
l.unique()
Erasel's last element
Erasel's first element
Erase the value inlat iterator positionpos
Erase the values inlfrom iterator positionspos1 topos2
Erase all elements in lthat matchvalue, using==to
compare items.
Replace all repeating sequences of a single element by a single
occurrence of that element.
l.front()l.back()
Return a reference to l's first elementReturn a reference to l's last element
l.begin()l.end()
Return an iterator positioned to l's first value
Return an iterator positioned 1 element past l's last value
l.rbegin()l.rend()
Return a reverse iterator positioned to l's last value
Return a reverse iterator positioned 1 element before l's first
value
l.sort();l.reverse();
Sort l's elements (using
-
7/30/2019 Chapter 08-Pointers and Linked Lists
75/75
l1.merge(l2);
l1.splice(pos, l2);
l1.splice(to, l2, from);
l1.splice(pos, l2,
first, last);
l1.swap(l2);
Remove all the elements in l2and merge them into l1; that
is, move the elements ofl2into l1 and place them so tha
the final list of elements is sorted using