You are on page 1of 45

11 Recursive Data Structures:

Linked Lists
COL 100 - Introduction to Computer Science
II Semester 2014-2015
Department of Computer Science and Engineering
Indian Institute of Technology Delhi

The STACK Data Structure


Items are placed in a column or STACK
new item is placed on top
item is removed also from top
LIFO order: Last In First Out
E.g.: Function call sequence

We wish to model this situation


push (x) places a new item on the top of Stack
pop () removes an item from top of stack
empty () returns true/false if stack is empty/nonempty
April 2015

(C) P. R. Panda, IIT Delhi

Stack Functions
Top of Stack
d
c
b
a

3
2
1
0

Top of Stack

Top of Stack
3
2
1
0
April 2015

d
c
b
a

x
d
c
b
a

4
3
PUSH (x) 2
1
0

Top of Stack
POP

2
1
0

(C) P. R. Panda, IIT Delhi

c
b
a
3

Array Implementation of Stack


Use array to store items
(integer type)
Need to keep track of the
current TOP of stack
push() increments top
pop() decrements top
empty() checks if top == -1

April 2015

(C) P. R. Panda, IIT Delhi

class Stack {
private:
int A[100];
int top;
public:
Stack ( ) {top = -1;}
void push (int x) {
A [++top] = x;
}
int pop () {
return A [top--];
}
bool empty () {
return top == -1;
}
};
4

Error Conditions
Check for Stack
overflow and underflow
pop() does not really
remove the element
only moves top

Improve upon this...


April 2015

(C) P. R. Panda, IIT Delhi

class Stack {
private:
int A[100];
int top;
public: // ...
void push (int x) {
if (top >= 99)
cout << Overflow;
else
A [++top] = x;
}
int pop () {
if (top == -1)
cout << Underflow;
else
return A [top--];
} // ...
};
5

Memory Allocation
Stack size was statically declared to be 100
Actual size not known at compile-time
depends on run-time data

If only 5 PUSH operations were carried out,


we are wasting 95 array locations
Use only as much memory as necessary
memory is precious resource
some other part of the program might need it
other programs might need it

April 2015

(C) P. R. Panda, IIT Delhi

Maintaining 2 Stacks
What if we wanted to maintain
2 stacks A and B in a given
memory space?
Stack A can grow to maximum
6 elements
but more space may be available
because B is not full

We can spread the Stack over


non-contiguous memory
regions

April 2015

(C) P. R. Panda, IIT Delhi

Bottom of
0
Stack A
1
2
3
Top of
4
Stack A
5
Bottom of
6
Stack B
7
Top of
8
Stack B
9
10
11
Free Space
Memory
7

Stacks in Non-contiguous Memory


Each element can
maintain the index of the
NEXT element
last in series can keep -1
or some other number
outside the range

All available memory


can be utilised
Stack A has 8 elements
Stack B has 3 elements
April 2015

(C) P. R. Panda, IIT Delhi

0
1
2
3
4
5
6
7
8
9
10
11

Data Next
-1
0
1
2
3
4
-1
6
7
5
9
Memory

Bottom of
Stack A

Bottom of
Stack B
Top of
Stack B
Top of
Stack A
Free Space
8

Overheads: Extra Space


Extra space required for
storing the NEXT element
Usually worth it
Each element can be large
One extra integer to keep track
of NEXT element may not add
too much
But tremendous extra flexibility

We now have a rudimentary


mechanism to utilise the
entire available memory
effectively
April 2015

(C) P. R. Panda, IIT Delhi

0
1
2
3
4
5
6
7
8
9
10
11

Data Next
-1
0
1
2
3
4
-1
6
7
5
9
Memory

Bottom of
Stack A

Bottom of
Stack B
Top of
Stack B
Top of
Stack A
Free Space
9

Managing Free Memory


Some memory management routine
needs to keep track of available and
occupied memory regions
These are new() and delete()
Index of NEXT element is simply the
POINTER to the next element
i.e., address of element
returned by new()
April 2015

(C) P. R. Panda, IIT Delhi

10

Stack Implementation using


Dynamic Memory Allocation
Allocate memory in push
De-allocate memory in pop
Ensures we never have extra memory
allocated for Stack
How do we modify earlier code?

April 2015

(C) P. R. Panda, IIT Delhi

11

Earlier Program
We dont have an
array any more
Elements returned by
new not necessarily
next to each other

April 2015

(C) P. R. Panda, IIT Delhi

class Stack {
private:
int A[100];
int top;
public: // ...
void push (int x) {
if (top >= 99)
cout << Overflow;
else
A [++top] = x;
}
int pop () {
if (top == -1)
cout << Underflow;
else
return A [top--];
} // ...
};
12

New Stack Declaration


Each stack element
has 2 fields
data
next: pointer to next
stack element

top points to top of


stack
initialised to 0 in
constructor

April 2015

class StackElem {
public:
int data;
StackElem *next;
};
class Stack {
private:
StackElem *top;
public:
Stack () {top = 0;}
// ...
};

(C) P. R. Panda, IIT Delhi

13

Dynamic Memory
Allocation
Memory allocated in
push
If new fails to find
available memory, it
returns 0
x filled into newly
allocated StackElem
Element next to p is 0

April 2015

class StackElem { public:


int data;
StackElem *next;
};
class Stack {
private:
StackElem *top;
public:
Stack () {top = 0;}
void push (int x) {
StackElem *p;
p = new StackElem;
if (!p) cout << Out of Memory;
else {
p->data = x;
p->next = top;
top = p
}
}
};

(C) P. R. Panda, IIT Delhi

14

Initialising and
Growing the Stack

Stack()
top = 0
push(6)
new returns 100
100
6
0
top = 100
push(7)
new returns 150
100
6
0
150

7
top = 150

April 2015

100

(C) P. R. Panda, IIT Delhi

class StackElem { public:


int data;
StackElem *next;
};
class Stack {
private:
StackElem *top;
public:
Stack () {top = 0;}
void push (int x) {
StackElem *p;
p = new StackElem;
if (!p) cout << Out of Memory;
else {
p->data = x;
p->next = top;
top = p
}
}
};
15

Initialising and
Growing the Stack
push(25)
new returns 250
100

150

100

250

25

150

top = 250

April 2015

(C) P. R. Panda, IIT Delhi

class StackElem {public:


int data;
StackElem *next;
};
class Stack {
private:
StackElem *top;
public:
Stack () {top = 0;}
void push (int x) {
StackElem *p;
p = new StackElem;
if (!p) cout << Out of Memory;
else {
p->data = x;
p->next = top;
top = p
}
}
};
16

Shrinking the
Stack
pop() removes the top
element from the stack
and returns the data
if stack is empty, report
error

Save the top data


Change top
Return saved top data

April 2015

class StackElem { public:


int data;
StackElem *next;
};
class Stack { private:
StackElem *top;
public:
int pop () {
StackElem *p; int x;
if (!top) {
cout << underflow);
return -1; // Invalid data
} else {
x = top->data;
p = top;
top = top->next;
delete p;
return(x};
}
}
};

(C) P. R. Panda, IIT Delhi

17

The Linked List Data Structure


Data structure to hold an arbitrary number of
elements
Size of data structure grows and shrinks during
program execution
NOT contiguous elements
each is dynamically allocated

Elements connected in a chain


Relevant operations
create a list (empty to begin with)
insert an element
also, insert at a particular position

delete an element
also, delete element at a particular position

search for an element


April 2015

(C) P. R. Panda, IIT Delhi

18

Graphically Representing the


Linked List
Initial List
data next
2
Head of List
Insert 7
data next
7
Head of List
Delete 2
data next
7
Head of List

data next
9

data next
6

0 or NULL
data next
2

data next
9

data next
9

data next
6

April 2015

data next
6

19
(C) P. R. Panda, IIT Delhi

Designing the Linked List

One list node

Design a single NODE


data content
next pointer to next element
in list
of type Node*

first points to Head of list


given the head, we can
access the other elements by
traversing the list
initialised to 0

April 2015

(C) P. R. Panda, IIT Delhi

data next
2
class Node {
int data;
Node *next;
};
class List {
private:
Node *first;
public:
List () {first = 0;}
};
20

Recursive Data Structure

One list node

Node has one of its


elements pointing to the
same type

data next
2
class Node {
int data;
Node *next;
};

Could we have:
April 2015

(C) P. R. Panda, IIT Delhi

class Node {
int data;
Node next;
};

??
21

Operations on the Linked List

Insert element x
Insert element x at a given position
Delete element x
Delete element at a given position
Search for element x

April 2015

(C) P. R. Panda, IIT Delhi

22

Searching in a Linked List


Traverse NEXT pointers until
first

element is found, or
end of list is reached
data next
2

data next
9

search (9)
1st iter:
p=
p->data = 2
2nd iter:
p=
p->data = 9
FOUND. Return true
April 2015

data next
6

(C) P. R. Panda, IIT Delhi

class Node {public:


int data;
Node *next;
};
class List {
private:
Node *first;
public:
List () {first = 0;}
bool search (int x) {
Node *p = first;
while (p) {
if (p->data == x)
return true;
p = p->next;
}
return false;
}
};
23

Searching in a Linked List


first
data next
2

data next
9

search (10)
1st iter:
p=
p->data = 2
2nd iter:
p=
p->data = 9
3rd iter:
p=
p->data = 6
p becomes 0
End of Loop. NOT FOUND
April 2015

data next
6

(C) P. R. Panda, IIT Delhi

class Node {public:


int data;
Node *next;
};
class List {
private:
Node *first;
public:
List () {first = 0;}
bool search (int x) {
Node *p = first;
while (p) {
if (p->data == x)
return true;
p = p->next;
}
return false;
}
};
24

Insert into Linked List


Allocate a new NODE
Fill in the data
New node becomes Head of the list
Initially:
first

data next
9

insert (2)
p=
fill 2 in p->data

April 2015

data next
6

data next
?

data next
2

(C) P. R. Panda, IIT Delhi

class Node {public:


int data;
Node *next;
};
class List {
private:
Node *first;
public:
List () {first = 0;}
void insert (int x) {
...
}
};

25

Insert Operation on a Linked List


Initially:
first

data next
9

data next
6

insert (list, 2)
data next
p=
2
?
p->data = 2
p p->next = first
first
data next
data next
data next
2
9
6
after insert (2):
data next
2
first

April 2015

data next
9

data next
6

(C) P. R. Panda, IIT Delhi

class Node {public:


int data;
Node *next;
};
class List {
private:
Node *first;
public:
List () {first = 0;}
void insert (int x) {
Node *p = new Node;
p->data = x;
p->next = first;
first = p;
}
};
26

Insert at a Given Position in a Linked List


i.e., at a specified location in the list
AFTER a given pointer pos

Allocate a new NODE p


Fill in the data
Rearrange pointers
p becomes NEXT node of pos
NEXT of p = old NEXT of pos

first

data next
9

data next
6

class Node {public:


int data;
Node *next;
};
class List {
private:
Node *first;
public:
List () {first = 0;}
void insert (Node *pos,int x) {
Node *p = new Node;
p->data = x;
p->next = pos->next;
pos->next = p;
}
};

data next
2
Corner cases: What if pos pointed to the last/first node?
April 2015

(C) P. R. Panda, IIT Delhi

27

Remove from Linked List


Given an element x
Delete Node in List containing x
Resulting structure should be a
valid Linked List
first
data next
9

data next
2

data next
6

class Node {public:


int data;
Node *next;
};
class List {
private:
Node *first;
public:
List () {first = 0;}
void remove (int x) {
...
}
};

remove (2)
April 2015

(C) P. R. Panda, IIT Delhi

28

Remove an Element from a Linked List


First search for data (x)
located at p

Rearrange pointers
NEXT of previous Node is NEXT
node

Delete memory allocated to p


first
data next
9

data next
2
p

data next
6

class Node {public:


int data;
Node *next;
};
class List {
private:
Node *first;
public:
List () {first = 0;}
void remove (int x) {
...
}
};

remove (2)
April 2015

(C) P. R. Panda, IIT Delhi

29

Remove from Linked List


Unfortunately, no access to
previous Node
Keep track of previous node q
p is always one step ahead of q
when search succeeds at p, q is
the previous node
first
data next
9
q

data next
2
p

data next
6

remove (2)
April 2015

(C) P. R. Panda, IIT Delhi

class Node {public:


int data;
Node *next;
};
class List {
private:
Node *first;
public:
void remove (int x) {
if (!first)... // 0 elems...fail
if (!first->next)... // 1 elem
Node *q=first;
Node *p = first->next;
while (p) {
if (p->data == x) {
q->next = p->next;
delete p;
return;
}
q = p;
p = p->next;
} cout << Failed;
}
};
30

Remove an Element at Given Position


i.e., delete element at a
specified location
AFTER a pointer pos

Rearrange pointers
NEXT of pos is NEXT of NEXT
of pos

Delete memory allocated to


pos->next
list
data next
9
pos
April 2015

data next
2

class Node {public:


int data;
Node *next;
};
class List {
private:
Node *first;
public:
void remove (Node *pos) {
if (!first || !pos || !first->next) // fail
Node *p = pos->next;
pos->next = p->next;
delete p;
}
};

data next
6

remove (pos)
(C) P. R. Panda, IIT Delhi

31

Remove an Element at Given Position


Cant delete first node this way
could interpret pos=0 to mean
delete Head of List

How about delete the Node


pointed to by pos?
need to traverse from Head to find
previous NODE
list
data next
9
pos
April 2015

data next
2

data next
6

remove (pos)
(C) P. R. Panda, IIT Delhi

class Node {public:


int data;
Node *next;
};
class List {
private:
Node *first;
public:
void remove (Node *pos) {
if (!first)...// fail
if (!pos) ...// delete first
if (!first->next)... // fail
Node *p = pos->next;
pos->next = p->next;
delete p;
}
};
32

Efficiency of Linked List


Operations
SPACE?
how much space for n-node list?

TIME?
Insert element x
Insert element x at a given position
Delete element x
Delete element at a given position
Search for element x
April 2015

(C) P. R. Panda, IIT Delhi

33

Arrays vs. Linked Lists


Space?

0
2

fixed/variable

Time?
insert
delete
search

April 2015

first

Array
1
9

2
6

Linked List
data next
2

(C) P. R. Panda, IIT Delhi

data next
9

data next
6

34

Limitation of Singly Linked List


Reaching PREVIOUS node is difficult
How to overcome this?
first

April 2015

data next
2

data next
9

(C) P. R. Panda, IIT Delhi

data next
6

35

Doubly Linked List


Add a Backward link in every node
Points to Previous node
first

data
2
prev

April 2015

next

data
9

next
prev

(C) P. R. Panda, IIT Delhi

data
6

next
prev

36

Doubly Linked List Implementation


first

p
data
2

q
next

prev
class NodeD {
int data;
Node *next;
Node *prev;
};
April 2015

data
9

r
next

prev

data
6

next
prev

NodeD *p = new NodeD;


NodeD *q = new NodeD;
NodeD * r = new NodeD;
p->next = q; p->prev = 0;
q->next = r; q->prev = p;
r->next = 0; r->prev = q;

(C) P. R. Panda, IIT Delhi

37

Singly vs. Doubly Linked Lists


Space
Time (insert, delete, search)
Singly
Linked
List
Doubly
Linked
List
April 2015

first

first

data next
2
data
2
prev

data next
9
next

data
9

data next
6
next

prev
(C) P. R. Panda, IIT Delhi

data
6

next
prev
38

Linked List Problems: 1

Insert End of Linked List


Given new data x, insert node at end of
linked list

April 2015

(C) P. R. Panda, IIT Delhi

39

Linked List Problems: 2

Merging Sorted Lists


Given two lists p and q with ordered
data, merge the two into one ordered
list t
p

10

April 2015

15

10

(C) P. R. Panda, IIT Delhi

20

15

20

40

Merging two
Sorted Lists
1. Special Cases
1.

empty lists

2. Loop (both lists nonempty)


1.
2.

Append node from right list


Advance list pointer

3. Append non-empty list

April 2015

Node *merge (Node *p, Node *q) {


if (!p) return q;
if (!q) return p;
Node *t=0, *s, *first;
while (p && q) {
if (p->data > q->data) {
s = p;
p = p->next;
} else {
s = q;
q = q->next;
}
if (t) {
t->next = s; t = s;
}
else {
first = t = s;
}
}
if (!p) t->next = q;
else t->next = p;
return first;
}

(C) P. R. Panda, IIT Delhi

41

Linked List Problems: 3

Least Recently Used Policy


Given a long sequence of requests, keep the results
of the last few (N) requests
same request is likely to repeat soon...if so, can respond fast
when new request arrives:
if result already saved, return it
else, throw out the Least Recently Used result of the
current N results

Principle of CACHE
Memory requests in Processor
File requests to disk/server
Web page requests to web server
April 2015

(C) P. R. Panda, IIT Delhi

42

LRU Illustration
New
Request
7

LRU

5
9
9
7

April 2015

(C) P. R. Panda, IIT Delhi

43

LRU Using Linked List


Linked List maintains LRU
order

New
Request

Head = Most Recent


Tail = Least Recent

On Access:

5
9

If Present
re-arrange List: bring to Head

If Absent
replace LRU element (tail)
bring to Head
April 2015

LRU

(C) P. R. Panda, IIT Delhi

44

LRU Using Doubly


Linked List
Could also be done with a singly linked list

first

last

5
9
9
7
April 2015

void LRU (int x) {


NodeD *p = first, *last;
while (p) {
if (p->data == x) { // FOUND
if (p != first) {
p->prev->next = p->next;
if (p->next)
p->next->prev = p->prev;
p->next = first;
first->prev = p;
first = p;
}
return;
}
last = p; p = p->next;
}
// NOT Found
last->prev->next = 0;
last->data = x; last->next = first;
first->prev = last;
first = last; first->prev = 0;
}

(C) P. R. Panda, IIT Delhi

45

You might also like