You are on page 1of 11

Linked Lists, Recursion, and ADTs

Overview
 Recursion
 Singly-Linked Lists
 Abstract Data Types

References
 Bruno R. Preiss: Data Structures and Algorithms with Object-
Oriented Design Patterns in C++. John Wiley & Sons, Inc. (1999)
 Richard F. Gilberg and Behrouz A. Forouzan: Data Structures - A
Pseudocode Approach with C. 2nd Edition. Thomson (2005)
 Russ Miller and Laurence Boxer: Algorithms Sequential & Parallel.
2nd Edition. Charles River Media Inc. (2005)
 Stanley B. Lippman, Josée Lajoie, and Barbara E. Moo: C++ Primer.
4th Edition. Addison-Wesley (2006)

58

Recursion
 If a procedure that contains within its body calls to itself,
then this procedure is called to be recursively defined.

 This approach of program specification is called recursion and


is found not only in programming.

 If we the define a procedure recursively, then there must


exist at least one sub-problem that can be solved directly,
that is without calling the procedure again.

 Note: A recursively defined procedure must always contain a


directly solvable sub-problem. Otherwise, this procedure does
not terminate.

59

Impossible Structures

60

1
Application of Recursion

 Recursion is an important problem-solving technique


in which a given problem is reduced to smaller
instances of the same problem.

 The general structure of a recursive definition is

Left-hand side Right-hand side

X =… X …
61

Factorials

 The factorial for positive integers is

n! = n * (n - 1) * … * 1

 The recursive definition:

"
1 if n = 0
n! =
$$
#
$
n * (n - 1)! if n > 0
$%

62

Calculating Factorials
 The recursive definition tells us exactly how to calculate a
factorial:

4! = 4* 3! Recursive step: n=4


= 4* (3 * 2!) Recursive step: n=3
= 4* (3 * (2 * 1!)) Recursive step: n=2
= 4* (3 * (2 * (1 * 0!))) Recursive step: n=1
= 4* (3 * (2 * (1 * 1))) Stop condition: n=0
= 4* (3 * (2 * 1))
= 4* (3 * 2)
= 4* 6
= 24

63

2
Recursive Factorial

int factorial( int n )


{
if (n == 0)
return 1; // stop condition
else
return n * factorial( n - 1 ); // recursive step
}

64

Towers of Hanoi

 Problem:
Move disks from a start peg to a target peg using a
middle peg.

 Challenge:
All disks have a unique size and at no time must a bigger
disk be placed on top of a smaller one.

65

Towers of Hanoi: Configuration


Start:

Start Middle Target

Finish:

Start Middle Target


66

3
A Recursive Solution
1. Move n–1 disks from Start to Middle:
S M T

2. Move 1 disk from Start to Target:


S M T

3. Move n-1 disks from Middle to Target:


S M T

67

A Recursive Solution: Intermediate


S M T
1:

S M T
2:

S M T
3:

S M T
4:

68

The Recursive Procedure

void move( int n, int start, int target, int middle )


{
if ( n > 0 )
{
move( n-1, start, middle, target );
cout << “Move disk ” << n << “ from ” << start
<< “ to ”<< finish “.” << endl;
move( n-1, middle, target, start );
}
}

69

4
Recursion is a prerequisite for linked lists!

70

Problems with Arrays

 An array is a contiguous storage that provides


insufficient abstractions for handling addition and
deletion of elements.

 Addition and deletion require n/2 shifts on average.

 The computation time is O(n).

 Resizing effects performance.

71

Deletion Requires Shift

3 5 29 20 4

Delete 5

29 20 4

3 29 20 4

72

5
Addition Requires Shift

3 29 20 4

Insert 50 after 29

20 4

3 29 50 20 4

73

Linked Lists
 A linked list is a sequence of data items, each connected to
the next by a pointer called next.

Data Data … Data Nil

 A data item may be a primitive value, a composite value, or


even another pointer.

 A linked list is a recursive data structure whose nodes refers


to nodes of the same type.

74

Nodes
DataType is application-specific
class Node
{
public:
DataType data;
Node* next;

Node( DataType aData, Node* aNext )


{
data = aData;
next = aNext;
}
};

75

6
Can we be more specific?

76

Templates

 Templates are blueprints from which classes


and/or functions automatically generated by the
compiler based on a set of parameters.

 Each time a template is used with different


parameters is used, a new version of the class or
function is generated.

 A new version of a class or function is called


specialization of the template.

77

Node Class Template


template<class DataType>
class Node
{
public:
DataType data;
Node* next;

Node( DataType aData, Node* aNext )


{
data = aData;
next = aNext;
}
};

78

7
Class Template Instantiation

typedef Node<int> IntegerNode;


typedef Node<IntegerNode> NodeOfIntegerNode;

 Types uses as arguments cannot be classes with


local scope.

 Once instantiated, a class template can be used as


any other class.

79

The Need for Pointers

 A linked-list is a dynamic data structure with a


varying number of nodes.

 Access to a linked-list is through a pointer variable


in which the base type is the same as the node
type:

Node<int>* pListOfInteger = (Node<int>*)0;

Here (Node<int> *)0 stands for Nil.

80

Node Construction

Node<int> *p, *q;

p = new Node<int>( 5, (Node<int>*)0 );


q = new Node<int>( 7, p );

p 5 Nil

q 7 5 Nil

81

8
Node Access
Node<int> *p, *q;
p = new Node<int>( 5, (Node<int>*)0 );
q = new Node<int>( 7, p );

a = p->data;
b = q->next->data;

a: p 5 Nil

b: q 7 5 Nil

82

Insert a Node
Node<int> r*;

r = new Node<int>( 6, (Node<int>*)0);


r->next = p;
q->next = r;

p 5 Nil

q 7 6 5 Nil

r 6 5 Nil

Observe the side effect on the node s!


83

Delete a Node
q 7 6 5 Nil

q->next = q->next->next;

p 5 Nil

q 7 5 Nil

r 6 5 Nil

Observe there is no side effect on the node s!


84

9
Insert at the Beginning

Node<int> *pList = (Node<int>*)0;

pList = new Node<int>( 5, pList );


pList = new Node<int>( 7, pList );

pList 5 Nil

pList 7 5 Nil

85

Insert at the End

 To insert a new node at the end of a linked list we


need to search for the end:

Node<int> *pList = (Node<int>*)0;


Node<int> **pToEnd = &pList;

while ( *pToEnd != (Node<int>*)0 )


{
pToEnd = &(*pToEnd->next); // pointer to next
}

*pToEnd = new Node<int>( 9, (Node<int>*)0 );

86

Insert at the End : The Pointers

pList 5 7 Nil

pToEnd * 9 Nil

pList 5 7 9 Nil

87

10
Insert at the end preserves the order
of list nodes!

88

Insert at the End with Aliasing


 Rather than using a Pointer-to-Pointer we can just record the
last next pointer.

Node<int> *pLastNode = (Node<int>*)0;


Node<int> *pNewNode = new Node<int>( 9, (Node<int>*)0 );

if ( *pList == (Node<int>*)0 )
{
pLastNode = pNewNode; // make new node last
pList = pLastNode; // set first node
}
else
{
pLastNode->next = pNewNode; // append new node
pLastNode = pNewNode; // make new node last
}
89

Complications with Singly-Linked Lists

 The deletion of a node at the end of a list


requires a search from the top to find the
new last node.

90

11

You might also like