2. 2
Stack ADT
• Recall that ADT is abstract data type, a set
of data and a set of operations that act
upon the data.
• In a stack, the set of data is the stack of
elements.
• Stack is known as a LIFO (last-in-first-out)
data structure because the last data to
enter the stack is the first to exit the stack.
3. 3
Stack ADT Operations
• push: places an element onto the top of a
stack.
• pop: removes an element from the top of the
stack.
• peek: which retrieves (copies) a value from the
top of the stack without removing it.
• an operation to determine whether or not the
stack is empty.
• an operation to empty out a stack.
4. 4
Push
• Push means place a new data element at
the top of the stack
11
5
17
3
stack
5. 5
Push (cont.)
• Push means place a new data element at
the top of the stack
11
5
17
3
stack
6. 6
Push (cont.)
• Push means place a new data element at
the top of the stack
3
11
5
17
stack
7. • Pop means take a data element off the top
of the stack
7
Pop
3
11
5
17
stack
8. • Pop means take a data element off the top
of the stack
8
Pop (cont.)
11
5
17
3
stack
9. • Pop means take a data element off the top
of the stack
9
Pop (cont.)
11
5
17
3
stack
10. 10
Peek
• Peek means retrieve the top of the stack
without removing it
3
11
5
17
3
stack
11. 11
Array Stack Class Template
3 template <typename T>
4 class Stack {
5 public:
6 Stack() { … }
7 ~Stack( ) { … }
8 void push( T& elementToPush ) { … }
9 bool pop( T& poppedElement ) { … }
10 bool peek( T& topElement ) { … }
11 bool isEmpty( ) const { … }
12 void makeEmpty( ) { … }
13 private:
14 T* elements; // dynamic array
15 int size;
16 int top;
17 };
used as an
index to the top
of the stack
14. 14
Array Stack Pop
elements
125 25 200 70
0 1 2 3
top
An element can’t really be removed from an
array, as one would think pop would achieve.
15. 15
Array Stack Pop
(cont.)
elements
125 25 200 70
0 1 2 3
top
client
The element 70 is at the top of the stack, and
what really happens during a pop, is that 70 is
returned to the client…
16. 16
Array Stack Pop
(cont.)
elements
125 25 200 70
0 1 2 3
top
and top is decremented…
client
17. 17
Array Stack Pop
(cont.)
elements
125 25 200 70
0 1 2 3
top
client
The element 70 is still in the array, but it is no
longer accessible. The next push will
overwrite it. Say, we would like to push 63…
18. 18
Array Stack Push
elements
125 25 200 70
0 1 2 3
top
First, top is incremented…
19. 19
Array Stack Push
(cont.)
elements
125 25 200 63
0 1 2 3
top
Then, 63 is pushed into that position…
20. 20
Is the Array Stack Full/Empty?
• An array stack is full when
– top == size - 1
• An array stack is empty when
– top == -1
21. 21
Linked-List Stack
• Stacks can also be implemented with a
linked list.
• The front node is the top of the stack.
22. Bob
Ali
22
Linked-List Stack
(cont.)
top
To pop, we remove the node at the front of the
linked list, and return the element to the client…
Ali
top
23. 23
Linked-List Stack
(cont.)
top
To push Cat, we place the new element in a node
and insert it at the front of the linked list…
Cat
top
Ali Ali
27. Linked-List Push into Empty Stack
27
32 void push( const T& element ) {
33 Node<T> *newNode = new Node<T>;
34 newNode->info = element;
35 if (top == NULL) { // if stack is empty.
36 newNode->next = NULL;
37 top = newNode;
38 }
top
39 else {
40 newNode->next = top;
41 top = newNode;
42 }
43 }
newNode
NULL
28. Linked-List Push into Empty Stack
28
(cont.)
32 void push( const T& element ) {
33 Node<T> *newNode = new Node<T>;
34 newNode->info = element;
35 if (top == NULL) { // if stack is empty.
36 newNode->next = NULL;
37 top = newNode;
38 }
39 else {
40 newNode->next = top;
41 top = newNode;
42 }
43 }
top
newNode
29. 29
Linked-List Push into Non-Empty
Stack
32 void push( const T& element ) {
33 Node<T> *newNode = new Node<T>;
34 newNode->info = element;
35 if (top == NULL) { // if stack is empty.
36 newNode->next = NULL;
37 top = newNode;
38 }
39 else { // stack is not empty.
40 newNode->next = top;
41 top = newNode;
42 }
43 } newNode
top
30. 30
Linked-List Push into Non-Empty
Stack (cont.)
32 void push( const T& element ) {
33 Node<T> *newNode = new Node<T>;
34 newNode->info = element;
35 if (top == NULL) { // if stack is empty.
36 newNode->next = NULL;
37 top = newNode;
38 }
39 else { // stack is not empty.
40 newNode->next = top;
41 top = newNode;
42 }
newNode
43 }
top
31. 31
Linked-List Peek
56 bool peek( T& element )
57 {
58 if ( top == NULL )
59 return false;
60 element = top->info;
61 return true;
62 }
32. 32
Linked-List Pop
56 bool pop( T& element )
57 {
58 if ( top == NULL )
59 return false;
60 element = top->info;
61 Node<T> *ptr = top;
62 top = top->next;
63 delete ptr;
64 return true;
65 }
33. 33
Linked-List Stack
isEmpty and makeEmpty
65 bool isEmpty( ) const
66 {
67 return top == NULL;
68 }
69
70 void makeEmpty( )
71 {
72 T temp;
73 while ( pop( temp ) );
74 }
34. 34
The Queue ADT
• The queue is a data structure that is like a
line of people
– When people join the line, they go at the end
– When people are served, they come off the
front of the line
• Queue is known as a FIFO (last-in, last-out)
data structure because the last data
to enter the queue is the last to exit from
the queue.
35. 35
Queue ADT Operations
• enqueue: add an element to the end of
the line
• dequeue: take an element from the front
of the line
• peek: retrieve (copy) the element at the
front of the line without removing it
• an operation to determine whether or not
the queue is empty
• an operation that will empty out the queue
36. 36
Queue (cont.)
• In addition to a pointer at the beginning of
the linked list (called front), a pointer to
the end of the linked list (called back) is
also maintained in the private section
• The back pointer makes it fast to add new
elements to the end of the queue – you
don’t have to use a loop to go all the way
through the queue to find the last node
43. 43
Linked-List Queue Enqueue
21 void enqueue( const T & element )
22 {
23 Node<T> *newNode = new Node<T>;
24 newNode->info = element;
25 newNode->next = NULL;
28 if (front == NULL) { // list is empty.
29 front = back = newNode;
30 }
31 else { // list is not empty.
32 back->next = newNode;
33 back = newNode;
34 }
35 }
newNode
44. Linked-List Queue Enqueue (cont.)
44
22 void enqueue( const T & element )
23 {
24 Node<T> *newNode = new Node<T>;
25 newNode->info = element;
26 newNode->next = NULL;
27 if (front == NULL) { // list is empty.
28 front = newNode;
29 back = front;
30 }
31 else { // list is not empty.
32 back->next = newNode;
33 back = newNode;
34 }
35 }
newNode
Case 1: The queue
is initially empty.
front
back
45. Linked-List Queue Enqueue (cont.)
45
22 void enqueue( const T & element )
23 {
24 Node<T> *newNode = new Node<T>;
25 newNode->info = element;
26 newNode->next = NULL;
27 if (front == NULL) { // list is empty.
28 front = newNode;
29 back = front;
30 }
31 else { // list is not empty.
32 back->next = newNode;
33 back = newNode;
34 }
35 }
newNode
Case 2: The queue
has nodes.
front
back
46. Linked-List Queue Enqueue (cont.)
46
22 void enqueue( const T & element )
23 {
24 Node<T> *newNode = new Node<T>;
25 newNode->info = element;
26 newNode->next = NULL;
27 if (front == NULL) { // list is empty.
28 front = newNode;
29 back = front;
30 }
31 else { // list is not empty.
32 back->next = newNode;
33 back = newNode;
34 }
35 }
newNode
Case 2: The queue
has nodes.
front
back
47. Returns false if client tries
to dequeue an empty
queue.
47
Linked-List Queue Dequeue
41 bool dequeue( T & deqElement )
42 {
43 if ( front == NULL)
44 return false;
Dequeue continued…
48. 48
Linked-List Queue
Dequeue (cont.)
45 deqElement = front->info;
46 Node<T> *ptr = front;
47 front = front->next;
48 delete ptr;
49 return true;
50 }
deqElement:
passed in by
reference
front ptr back
52. 52
Linked-List Queue
isEmpty and makeEmpty
65 bool isEmpty( ) const
66 {
67 return front == NULL;
68 }
69
70 void makeEmpty( )
71 {
72 T temp;
73 while ( dequeue( temp ) );
74 }
53. 53
Array Queue
• Similar to the linked-list queue, there are 2
attributes called front and back, but they
are indexes into an array instead of
pointers.
• When enqueuing, the back index is
incremented, and when dequeuing, the
front index is incremented.
54. 54
Array Queue Class Template
3 template <typename T>
4 class Queue {
5 public:
6 Queue( ) { … }
7 ~Queue( ) { … }
8 void enqueue( T element ) { …
9 bool dequeue( T & deqElement ) { … }
10 bool peek( T & frontElement ) { … }
11 bool isEmpty( ) const { … }
12 void makeEmpty( ) { … }
13 private:
14 T *elements;
15 int size
16 int front;
17 int back;
18 };
65. 65
Array Queue
Enqueue / Dequeue (cont.)
0 1 2 3 4 5 6 7
front back
We have reached the
end of array. How to
enqueue? ?
DEQUEUE
DEQUEUE
ENQUEUE
ENQUEUE
DEQUEUE
DEQUEUE
ENQUEUE
DEQUEUE
DEQUEUE
ENQUEUE
66. 66
Array Queue
Enqueue / Dequeue (cont.)
0 1 2 3 4 5 6 7
front back
We could double the size of the array
here.
But if we keep doing this, we may
have a million elements in the array,
but only a few at the end are used!
DEQUEUE
DEQUEUE
ENQUEUE
ENQUEUE
DEQUEUE
DEQUEUE
ENQUEUE
DEQUEUE
DEQUEUE
ENQUEUE
67. 67
Array Queue
Enqueue / Dequeue (cont.)
0 1 2 3 4 5 6 7
back front
We handle this problem by having the
back wrap around to the beginning of
the array.
The front also wraps to the beginning
when it reaches the end of the array
DEQUEUE
DEQUEUE
ENQUEUE
ENQUEUE
DEQUEUE
DEQUEUE
ENQUEUE
DEQUEUE
DEQUEUE
ENQUEUE
68. 68
Is Array Queue Full/Empty?
• An array queue is empty when
– front = -1
• An array queue has one element when
– front = back
• An array queue is full when
– back + 1 = front
69. 69
A Full Array Queue
0 1 2 3 4 5 6 7
back front
If the next operation is ENQUEUE, the array
capacity will need to be doubled