Title: Chap 4' Queues and Linked List
1Chap 4. Queues and Linked List
2Overview
- Queue. Usage of Queue
- Implementation of Queue
- Array
- Linked List
3Queue
enqueue
dequeue
front
rear
A queue is open at two ends. You can only add
entry (enqueue) at the rear , and delete entry
(dequeue) at the front. Note that you cannot
add/extract entry in the middle of the queue.
4First-in First-out (FIFO)
The first one enqueued is the first one dequeued.
(FIFO)
When we enqueue entries in the queue and then
dequeue them one by one, we will get the entries
in the same order.
5Usage of Queue
- Queues in the real world
- Queue of persons in front of counter
- Queue of jobs to be done
- Message queue in Windows
- Print queue
- I/O buffer
6The Queue Module
The Queue module provides the type Queue with
the following functions to work on queues. void
CreateQueue (Queue Q) void Enqueue (QueueEntry
x, Queue Q) void Dequeue (QueueEntry x, Queue
Q) int QueueEmpty (Queue Q) int QueueFull
(Queue Q) void ClearQueue (Queue Q) int
QueueSize (Queue Q) void QueueFront (QueueEntry
x, Queue Q) void PrintQueue (Queue Q)
Dont worry about the implementation of these
functions, yet.
QueueEmpty does not modify the queue.
Nonetheless, we use pointer to Queue for
efficiency reason.
7Example
include ltstdio.hgt include "queue.h" int main ()
Queue Q QueueEntry x CreateQueue(Q)
Enqueue('a', Q) Enqueue('b', Q)
Enqueue('c', Q) PrintQueue(Q) Dequeue(x,
Q) PrintQueue(Q) ClearQueue(Q) return
0
The type Queue and the functions CreateQueue,
Enqueue and Dequeue are defined in the queue.h
and queue.cpp.
Remember, call CreateQueue before using the
queue, and call ClearQueue when the queue is no
longer used.
8Exercise
include ltstdio.hgt include "stack.h" / stack
of char / include "queue.h" / queue of char
/ int main ( ) char x Queue Q Stack S
CreateQueue(Q) CreateStack(S) Enqueue('a',
Q) Enqueue('b', Q) Enqueue('c', Q)
Enqueue('d', Q) Enqueue('e', Q) Enqueue('f',
Q) for (int i0 ilt3 i) Dequeue(x, Q)
Push(x, S) while (!StackEmpty(S))
Pop(x, S) Enqueue(x, Q) / draw the
content of Q and S at this point of time /
return 0
Q1. Draw the queue and the stack.
9Array implementation, 1st trial
deQ A,B,C, then enQ F and G..
D
E
G
A
B
C
D
E
F
rear 5
rear 4
front 3
We cannot enqueue G because the rear has
reached the end of the array.
front 0
entry
entry
10Circular Array
G
If we view the array as a circle, the cell after
the 5th cell is the 0th cell.
entry
5
front 3
4
rear 5 ? 0
3
2
1
G
0
entry
11Array implementation
define MAXQUEUE 6 typedef char QueueEntry
struct Queue int count int front, rear
QueueEntry entryMAXQUEUE
Number of entries in the Q
front 3
rear 5
5
4
3
Change the definition of QueueEntry to match your
application. E.g. if you need a queue of struct
Student, writetypedef Student QueueEntry
The capacity of the queue. In array
implementation, we have to fix the size of array
in compile time.
2
1
0
entry
count 3
12Array implementation
G
G
front 0
front 3
front 1
front 0
rear 2
rear 0
rear 0
rear 0
5
5
5
5
4
4
4
4
3
3
3
3
2
2
2
2
1
1
1
1
0
0
0
0
entry
entry
entry
entry
count 3
count 4
count 1
count 0
13Create Queue
void CreateQueue (Queue Q) Q-gtcount 0
Q-gtfront 0 Q-gtrear -1
We can also use these values front
1 2 3 4 5 0 rear 0 1 2 3 4 5 MAXQUEUE
- 1 We have to make sure that when we enqueue
the first entry, front and rear point to that
entry.
14Enqueue
void Enqueue (QueueEntry x, Queue Q) if
(QueueFull(Q)) printf("Cannot ")
else Q-gtcount Q-gtrear
(Q-gtrear1) MAXQUEUE Q-gtentryQ-gtrear
x
Remember to update count whenever the number of
entries in the Q changes!
This formula is the same as if
(Q-gtrearMAXQUEUE-1) Q-gtrear 0 else
Q-gtrear
15Dequeue
void Dequeue (QueueEntry x, Queue Q) if
(QueueEmpty(Q)) printf(" ") else
Q-gtcount -- x Q-gtentryQ-gtfront
Q-gtfront (Q-gtfront1) MAXQUEUE
Remember to check underflow and overflow properly.
Front is updated in a similar way as rear in
Enqueue.
16Traversing a Queue
void PrintQueue (Queue Q) int c int i
Q-gtfront int sizeQueueSize(Q) printf("ltlt
") for (c1 cltsize c) printf("c
", Q-gtentryi) i (i1) MAXQUEUE
printf("ltlt")
17Exercise
Q2. Write the following functions on array
implementation of Queue.
int QueueEmpty (Queue Q) int QueueFull (Queue
Q) void ClearQueue (Queue Q) int QueueSize
(Queue Q) void QueueFront (QueueEntry x, Queue
Q)
18Code Listing, 1
define MAXQUEUE 6 typedef char
QueueEntry struct Queue int count int
front, rear QueueEntry entryMAXQUEUE ext
ern void CreateQueue (Queue Q) extern void
Enqueue (QueueEntry x, Queue Q) extern void
Dequeue (QueueEntry x, Queue Q) extern int
QueueEmpty (Queue Q) extern int QueueFull
(Queue Q) extern void ClearQueue (Queue
Q) extern int QueueSize (Queue Q) extern void
QueueFront (QueueEntry x, Queue Q) extern void
PrintQueue (Queue Q)
queue.h
Notice what is placed in the header file.
19Code Listing, 2
include ltstdio.hgt include "queue.h" void
CreateQueue (Queue Q) Q-gtcount 0
Q-gtfront 0 Q-gtrear -1 void Enqueue
(QueueEntry x, Queue Q) if (QueueFull(Q))
printf("Cannot enqueue item into full
queue.") else Q-gtcount Q-gtrear
(Q-gtrear1) MAXQUEUE Q-gtentryQ-gtrear
x
queue.cpp, p.1
20Code Listing, 3
void Dequeue (QueueEntry x, Queue Q) if
(QueueEmpty(Q)) printf("Cannot dequeue from
empty queue.") else Q-gtcount -- x
Q-gtentryQ-gtfront Q-gtfront (Q-gtfront1)
MAXQUEUE int QueueEmpty (Queue Q)
return Q-gtcount lt0 int QueueFull (Queue Q)
return Q-gtcount gt MAXQUEUE
queue.cpp, p.2
21Code Listing, 4
void ClearQueue (Queue Q) Q-gtcount 0
Q-gtfront 0 Q-gtrear -1 int QueueSize
(Queue Q) return Q-gtcount void
QueueFront (QueueEntry x, Queue Q) if
(QueueEmpty(Q)) printf("Cannot QueueFront for
empty queue") else x Q-gtentryQ-gtfront
queue.cpp, p.3
22Code Listing, 5
void PrintQueue (Queue Q) int c int i
Q-gtfront int sizeQueueSize(Q) printf("ltlt
") for (c1 cltsize c) printf("c
", Q-gtentryi) i (i1) MAXQUEUE
printf("ltlt\n")
queue.cpp, p.4
23Linked list implementation
Which one is better?
24Linked list implementation
typedef char QueueEntry struct QueueNode
QueueEntry entry QueueNode next struct
Queue QueueNode front QueueNode rear
25Create queue
void CreateQueue (Queue Q) Q-gtfront NULL
Q-gtrear NULL
front
rear
26Enqueue
D
1. Initialize new node at np
np
D
27Enqueue
void Enqueue (QueueEntry x, Queue Q)
QueueNode np np (QueueNode) malloc
(sizeof(QueueNode)) // error checking missing
np-gtentry x np-gtnext NULL if
(QueueEmpty(Q)) Q-gtfront Q-gtrear np
else Q-gtrear-gtnext np Q-gtrear
np
Q3. Add error checking for insufficient memory.
Special handling for empty queue
28Dequeue
1. dp front
29Dequeue
void Dequeue (QueueEntry x, Queue Q)
QueueNode dp if (QueueEmpty(Q))
printf("Cannot dequeue from empty queue")
else dp Q-gtfront Q-gtfront
Q-gtfront-gtnext if (Q-gtfrontNULL) Q-gtrear
NULL x dp-gtentry free(dp)
Special handling for empty queue after dequeue
30Handling empty queue
enqueue
front
rear
front
A
rear
dequeue
Empty queue has to be handled specially in
Enqueue and Dequeue! Read the code carefully.
31Exercise
Q3. Write the following functions on linked list
implementation of Queue.
int QueueEmpty (Queue Q) int QueueFull (Queue
Q) void ClearQueue (Queue Q) int QueueSize
(Queue Q) void QueueFront (QueueEntry x, Queue
Q) void PrintQueue (Queue Q)
32Exercise
typedef char QueueEntry struct QueueNode
QueueEntry entry QueueNode next struct
Queue QueueNode front QueueNode rear
int size
Q4. Add a field size to store the number of
nodes in the queues in our linked list
implementation of queue. Review the operations
of the Queue module and modify them accordingly.
33Deque
addReardelRear
addFrontdelFront
A
B
C
front
rear
A double-ended queue (Deque) is open at two ends.
You can add/delete entry (addRear/ delRear) at
the rear , or add/delete entry (addFront/
delFront) at the front. But you cannot add/delete
entry in the middle of the deque.