You are on page 1of 66

DATA STRUCTURES

COL 106

AMIT KUMAR, SHWETA AGRAWAL


Why are we studying Data Structures ?
Modern world all about … DATA
Dealing with data…
• How to use it ?
• How to store it ?
• How to process it ?
• How to gain “knowledge” from it ?
• How to keep it secret?
Dealing with data…
• How to use it ?
• How to store it ?
• How to process it ?
• How to gain “knowledge” from it ?
• How to keep it secret?
How should data be stored?
Depends on your requirement
Data is diverse ..
But we have some building blocks
To store our big data
Elementary Data “Structures”
• Arrays head

• Lists
• Stacks 2
1

• Queues 3 4
7 8
• Trees 5 6

F R

In some languages these are basic data types – in others they need
to be implemented
10
Stacks
Stack
A list for which Insert and Delete are allowed
only at one end of the list (the top)
– LIFO – Last in, First out

Pop Pop
Push
What is this good for ?
• Page-visited history in a Web browser
What is this good for ?
• Page-visited history in a Web browser
• Undo sequence in a text editor
What is this good for ?
• Page-visited history in a Web browser
• Undo sequence in a text editor
• Saving local variables when one function
calls another, and this one calls another
How should we represent it ?
• Write code in python ?
How should we represent it ?
• Write code in python ?
• Write code in C ?
How should we represent it ?
• Write code in python ?
• Write code in C ?
• Write code in Java ?

Aren’t we essentially doing the same


thing?
Abstract Data Type

A mathematical definition of objects, with


operations defined on them

19
Examples

• Basic Types
– integer, real (floating point), boolean (0,1),
character
• Arrays
– A[0..99] : integer array
0 1 2 3 4 5 6 7 99
A 2 1 3 3 2 9 9 6

10

– A[0..99] : array of images


0 1 2 99
20
ADT: Array

A mapping from an index set, such as


{0,1,2,…,n}, into a cell type
Objects: set of cells
Operations:
• create(A,n)
• put(A,v,i) or A[i] = v
• value(A,i)

21
Abstract Data Types (ADTs)
• An abstract data type (ADT) is an
abstraction of a data structure

• An ADT specifies:
–Data stored
–Operations on the data
–Error conditions associated with
operations
22
ADT for stock trade
– The data stored are buy/sell orders
– The operations supported are
• order buy (stock, shares)
• order sell(stock, shares )
• void cancel(order)
– Error conditions:
• Buy/sell a nonexistent stock
• Cancel a nonexistent order
23
Stack ADT
Objects:
A finite sequence of nodes
Operations:
• Create
• Push: Insert element at top
• Top: Return top element
• Pop: Remove and return top element
• IsEmpty: test for emptyness
Exceptions
• Attempting the execution of an operation of ADT
may sometimes cause an error condition, called
an exception
• Exceptions are said to be “thrown” by an
operation that cannot be executed
• In the Stack ADT, operations pop and top cannot
be performed if the stack is empty
• Attempting the execution of pop or top on an
empty stack throws an EmptyStackException

25
Exercise: Stacks
• Describe the output of the following series of stack
operations
– Push(8)
– Push(3)
– Pop()
– Push(2)
– Push(5)
– Pop()
– Pop()
– Push(9)
– Push(1)

26
C++ Run-time Stack
main() {
• The C++ run-time system keeps int i;
track of the chain of active i = 5; bar
functions with a stack foo(i); PC = 1
• When a function is called, the } m=6
run-time system pushes on the foo(int j)
stack a frame containing { foo
– Local variables and return value int k; PC = 3
k = j+1; j=5
– Program counter, keeping track of bar(k); k=6
the statement being executed }
• When a function returns, its bar(int m) main
frame is popped from the stack { PC = 2
and control is passed to the …
i=5
method on top of the stack }

27
Parentheses Matching
• Each “(”, “{”, or “[” must be paired with a
matching “)”, “}”, or “[”
– correct: ( )(( )){([( )])}
– correct: ((( )(( )){([( )])}
– incorrect: )(( )){([( )])}
– incorrect: ({[ ])}
– incorrect: (

Stacks 28
Parentheses Matching Algorithm
Algorithm ParenMatch(X,n):
Input: An array X of n tokens, each of which is either a grouping symbol, a
variable, an arithmetic operator, or a number
Output: true if and only if all the grouping symbols in X match
Let S be an empty stack
for i=0 to n-1 do
if X[i] is an opening grouping symbol then
S.push(X[i])
else if X[i] is a closing grouping symbol then
if S.isEmpty() then
return false {nothing to match with}
if S.pop() does not match the type of X[i] then
return false {wrong type}
if S.isEmpty() then
return true {every symbol matched}
else
return false {some symbols were never matched}

Stacks 29
Postfix Evaluator
• 536*+7- =?

Stacks 30
Array-based Stack
Algorithm size()
• A simple way of return t + 1
implementing the
Stack ADT uses an Algorithm pop()
array if empty() then
throw EmptyStackException
• We add elements else
from left to right t = t - 1
• A variable keeps track return S[t + 1]
of the index of the
top element


S
0 1 2 t
Array-based Stack (cont.)
• The array storing the
stack elements may Algorithm push(o)
become full if t = S.length - 1 then
• A push operation will throw FullStackException
then throw a else
FullStackException t = t + 1
– Limitation of the S[t] = o
array-based
implementation
– Not intrinsic to the
Stack ADT


S
0 1 2 t
32
Performance and Limitations
- array-based implementation of stack ADT

• Performance
– Let n be the number of elements in the stack
– The space used is O(n)
– Each operation runs in time O(1)
• Limitations
– The maximum size of the stack must be defined a
priori , and cannot be changed
– Trying to push a new element into a full stack causes
an implementation-specific exception

33
Growable Array-based Stack

• In a push operation, when the


array is full, instead of
Algorithm push(o)
throwing an exception, we if t = S.length - 1
can replace the array with a then
A = new array of
larger one size …
for i = 0 to t do
• How large should the new A[i] = S[i]
array be? S = A
t = t + 1
– incremental strategy: increase S[t] = o
the size by a constant c
– doubling strategy: double the
size
Comparison of the
Strategies

• We compare the incremental strategy and the


doubling strategy by analyzing the total time
T(n) needed to perform a series of n push
operations
• We assume that we start with an empty stack
represented by an array of size 1
• We call amortized time of a push operation
the average time taken by a push over the
series of operations, i.e., T(n)/n
35
Incremental Strategy Analysis

• We replace the array k = n/c times


• The total time T(n) of a series of n push
operations is proportional to
• n + c + 2c + 3c + 4c + … + kc =
• n + c(1 + 2 + 3 + … + k) =
• n + ck(k + 1)/2
• Since c is a constant, T(n) is O(n + k2), i.e.,
O(n2)
• The amortized time of a push operation is O(n)

36
Doubling Strategy Analysis
• We replace the array k = log2 n
times
geometric series
• The total time T(n) of a series of n
push operations is proportional to 2
• n + 1 + 2 + 4 + 8 + …+ 2k = 4
1 1
• n + 2k + 1 -1 = 2n -1
• T(n) is O(n) 8
• The amortized time of a push
operation is O(1)

37
Stack Interface in C++
template <typename Object>
• Interface class Stack {
corresponding to our public:
int size();
Stack ADT bool isEmpty();
• Requires the Object& top()
throw(EmptyStackException);
definition of class void push(Object o);
EmptyStackException Object pop()
throw(EmptyStackException);
• Most similar STL };
construct is vector

38
Array-based Stack in C++
template <typename Object> bool isEmpty()
class ArrayStack { { return (t < 0); }
private:
int capacity; // stack capacity Object pop()
Object *S; // stack array {
int top; // top of stack if(isEmpty())
public: throw EmptyStackException
ArrayStack(int c) { (“Access to empty stack”);
capacity = c; return S[t--];
S = new Object[capacity]; }
t = –1; // … (other functions omitted)
}

39
Singly Linked List
• A singly linked list is a
concrete data next
structure consisting of
a sequence of nodes
• Each node stores
– element elem node
– link to the next node

A B C D
40
Stack with a Singly Linked List
• We can implement a stack with a singly linked list
• The top element is stored at the first node of the list
• The space used is O(n) and each operation of the
Stack ADT takes O(1) time
nodes

top t 

elements
2/6/2018 2:23 AM
Vectors 41
Exercise
• Describe how to implement a stack using a
singly-linked list
– Stack operations: push(x), pop( ), size(),
isEmpty()
– For each operation, give the running time

2/6/2018 2:23 AM
Vectors 42
Stack Summary
• Stack Operation Complexity for Different
Implementations
Array Array List
Fixed-Size Expandable (doubling Singly-
strategy) Linked
Pop() O(1) O(1) O(1)

Push(o) O(1) O(n) Worst Case O(1)


O(1) Best Case
O(1) Average Case
Top() O(1) O(1) O(1)

Size(), isEmpty() O(1) O(1) O(1)

2/6/2018 2:23 AM
Vectors 43
Queues

44
Outline and Reading
• The Queue ADT (§5.2.1)
• Implementation with a circular array (§5.2.4)
– Growable array-based queue
• List-based queue

45
The Queue ADT
• The Queue ADT stores arbitrary • Auxiliary queue operations:
objects – front(): returns the element at
• Insertions and deletions follow the front without removing it
the first-in first-out (FIFO) – size(): returns the number of
scheme elements stored
• Insertions are at the rear of the – isEmpty(): returns a Boolean
queue and removals are at the value indicating whether no
front of the queue elements are stored
• Main queue operations:
– enqueue(object o): inserts
• Exceptions
element o at the end of the – Attempting the execution of
queue dequeue or front on an empty
– dequeue(): removes and returns queue throws an
the element at the front of the EmptyQueueException
queue

46
Exercise: Queues
• Describe the output of the following series of queue
operations
– enqueue(8)
– enqueue(3)
– dequeue()
– enqueue(2)
– enqueue(5)
– dequeue()
– dequeue()
– enqueue(9)
– enqueue(1)

47
Applications of Queues
• Direct applications
– Waiting lines
– Access to shared resources (e.g., printer)

• Indirect applications
– Auxiliary data structure for algorithms
– Component of other data structures

48
Array-based Queue
• Use an array of size N in a circular fashion
• Two variables keep track of the front and rear
– f index of the front element
– r index immediately past the rear element
• Array location r is kept empty

normal configuration
Q
0 1 2 f r

wrapped-around configuration
Q
0 1 2 r f
49
Queue Operations
• We use the modulo Algorithm size()
return (N + r – f) mod N
operator
(remainder of Algorithm isEmpty()
return (f = r)
division)

Q
0 1 2 f r

Q
0 1 2 r f

50
Queue Operations (cont.)
• Operation enqueue throws an Algorithm enqueue(o)
exception if the array is full if size() = N - 1 then
throw FullQueueException
• This exception is
else
implementation-dependent
Q[r] = o
r = (r + 1) mod N

Q
0 1 2 f r

Q
0 1 2 r f

51
Queue Operations (cont.)
• Operation dequeue Algorithm dequeue()
throws an exception if isEmpty() then
throw EmptyQueueException
if the queue is else
empty o = Q[f]
• This exception is f = (f + 1) mod N
specified in the return o
queue ADT

Q
0 1 2 f r

Q
0 1 2 r f
52
Performance and Limitations
- array-based implementation of queue ADT

• Performance
– Let n be the number of elements in the queue
– The space used is O(n)
– Each operation runs in time O(1)
• Limitations
– The maximum size of the queue must be defined a
priori , and cannot be changed
– Trying to enqueue an element into a full queue causes
an implementation-specific exception
Growable Array-based Queue
• In an enqueue operation, when the array is full,
instead of throwing an exception, we can
replace the array with a larger one
• Similar to what we did for an array-based stack
• The enqueue operation has amortized running
time
– O(n) with the incremental strategy
– O(1) with the doubling strategy

54
Exercise

• Describe how to implement a queue using a


singly-linked list
– Queue operations: enqueue(x), dequeue(),
size(), isEmpty()
– For each operation, give the running time

Vectors
Queue with a Singly Linked List
• We can implement a queue with a singly linked list
– The front element is stored at the head of the list
– The rear element is stored at the tail of the list
• The space used is O(n) and each operation of the Queue ADT takes O(1)
time
• NOTE: we do not have the limitation of the array based implementation
on the size of the stack b/c the size of the linked list is not fixed, I.e., the
queue is NEVER full.
r

nodes
rear
front
f 

elements
56
Informal C++ Queue Interface
template <typename Object>
• Informal C++ class Queue {
interface for our public:
int size();
Queue ADT bool isEmpty();
• Requires the Object& front()
throw(EmptyQueueException);
definition of class void enqueue(Object o);
EmptyQueueException Object dequeue()
throw(EmptyQueueException);
• No corresponding };
built-in STL class

57
Queue Summary
• Queue Operation Complexity for Different
Implementations
Array Array List
Fixed-Size Expandable (doubling Singly-
strategy) Linked
dequeue() O(1) O(1) O(1)

enqueue(o) O(1) O(n) Worst Case O(1)


O(1) Best Case
O(1) Average Case
front() O(1) O(1) O(1)

Size(), isEmpty() O(1) O(1) O(1)

2/6/2018 2:23 AM
Vectors 58
The Double-Ended Queue ADT (§5.3)
• The Double-Ended Queue, or Deque, • Auxiliary queue operations:
ADT stores arbitrary objects. – first(): returns the element at the
(Pronounced ‘deck’) front without removing it
• Richer than stack or queue ADTs. – last(): returns the element at the
Supports insertions and deletions at front without removing it
both the front and the end.
– size(): returns the number of
• Main deque operations: elements stored
– insertFirst(object o): inserts element
o at the beginning of the deque
– isEmpty(): returns a Boolean value
indicating whether no elements are
– insertLast(object o): inserts element
o at the end of the deque
stored
– RemoveFirst(): removes and returns • Exceptions
the element at the front of the – Attempting the execution of
queue dequeue or front on an empty
– RemoveLast(): removes and returns queue throws an
the element at the end of the queue EmptyDequeException

59
Doubly Linked List
• A doubly linked list provides a natural prev next
implementation of the Deque ADT
• Nodes implement Position and store:
– element
– link to the previous node elem node
– link to the next node
• Special trailer and header nodes

header nodes/positions trailer

elements
60
Deque with a Doubly Linked List
• We can implement a deque with a doubly linked list
– The front element is stored at the first node
– The rear element is stored at the last node
• The space used is O(n) and each operation of the
Deque ADT takes O(1) time

first first last

elements
61
Implementing Deques with Doubly
Linked Lists
Here’s a visualization of
the code for
removeLast().

62
Performance and Limitations
- doubly linked list implementation of deque ADT

• Performance
– Let n be the number of elements in the stack
– The space used is O(n)
– Each operation runs in time O(1)
• Limitations
– NOTE: we do not have the limitation of the array
based implementation on the size of the stack b/c the
size of the linked list is not fixed, I.e., the deque is
NEVER full.
Deque Summary
• Deque Operation Complexity for Different
Implementations
Array Array List List
Fixed- Expandable Singly- Doubly-
Size (doubling strategy) Linked Linked
removeFirst(), O(1) O(1) O(n) for O(1)
removeLast() one at list
tail, O(1) for
other
insertFirst(o), O(1) O(n) Worst Case O(1) O(1)
InsertLast(o) O(1) Best Case
O(1) Average Case
first(), last O(1) O(1) O(1) O(1)

Size(), O(1) O(1) O(1) O(1)


isEmpty()
2/6/2018 2:23 AM
Vectors 64
Implementing Stacks and Queues with
Deques

Stacks with Deques:

Queues with Deques:

65
The Adaptor Pattern
• Using a deque to implement a stack or queue is an example of the
adaptor pattern. Adaptor patterns implement a class by using
methods of another class

• In general, adaptor classes specialize general classes

• Two such applications:


-- Specialize a general class by changing some methods.
Ex: implementing a stack with a deque.
-- Specialize the types of objects used by a general class.
Ex: Defining an IntegerArrayStack class that adapts
ArrayStack to only store integers.

66

You might also like