chapter 08-pointers and linked lists

Upload: hardeepcharming

Post on 04-Apr-2018

224 views

Category:

Documents


0 download

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