Stacks and queues Geoffs selfchecklist q No i

  • Slides: 26
Download presentation
Stacks and queues Geoff’s self-checklist: q No i. Clickers today q Record lecture October

Stacks and queues Geoff’s self-checklist: q No i. Clickers today q Record lecture October 26, 2020 Array resizing Stack implementation Queue ADT Hassan Khosravi / Geoffrey Tien 1

Announcements • Lab 3 quiz this week – Stacks – know how to use

Announcements • Lab 3 quiz this week – Stacks – know how to use push/pop • If you intend to attend L 1 M, please register officially! – release of quiz material is linked to your registration on SSC • Lab 4 in-lab starts next week October 26, 2020 Hassan Khosravi / Geoffrey Tien 2

Complexity of array resizing • • What would the average complexity be if the

Complexity of array resizing • • What would the average complexity be if the array grows by a constant amount? October 26, 2020 Hassan Khosravi / Geoffrey Tien 3

Stack implementation Using a linked list • From a client perspective, usage of the

Stack implementation Using a linked list • From a client perspective, usage of the stack involves only calling stack functions (e. g. push, pop, peek, etc. ) – The data storage can be implemented with other data structures • With a singly-linked list, the front of the list is accessed easily – The stack inserts and removes from the top, so let's insert and remove from the front of the list! top October 26, 2020 18 top 18 27 27 52 52 34 34 Hassan Khosravi / Geoffrey Tien 4

Stack implementation Using a linked list struct Node { int data; struct Node* next;

Stack implementation Using a linked list struct Node { int data; struct Node* next; }; typedef struct { struct Node* top; } Stack; void initialize(Stack* st) { st->top = NULL; } int is. Empty(Stack* st) { if (st->top == NULL) return TRUE; else return FALSE; } mystack top October 26, 2020 3 4 6 Hassan Khosravi / Geoffrey Tien 7 5

Stack implementation Using a linked list int push(Stack* st, int val) { struct Node*

Stack implementation Using a linked list int push(Stack* st, int val) { struct Node* newnode = (struct Node*) malloc(sizeof(struct Node)); if (newnode == NULL) return FALSE; push(&mystack, 3); newnode->data = val; push(&mystack, 5); newnode->next = st->top; push(&mystack, 7); st->top = newnode; return TRUE; } 7 mystack top 5 newnode 3 October 26, 2020 Hassan Khosravi / Geoffrey Tien 6

Stack implementation Using a linked list int pop(Stack* st) { if (!is. Empty(st)) {

Stack implementation Using a linked list int pop(Stack* st) { if (!is. Empty(st)) { struct Node* temp = st->top; st->top = st->top->next; free(temp); temp = NULL; return TRUE; } return FALSE; } pop(&mystack); 7 mystack top 5 temp 3 October 26, 2020 Hassan Khosravi / Geoffrey Tien 7

Stack implementation Using a linked list int peek(Stack* st) { if (!is. Empty(st)) return

Stack implementation Using a linked list int peek(Stack* st) { if (!is. Empty(st)) return st->top->data; else return FALSE; } 7 mystack top 5 3 • Notice that the function signatures for the array-based implementation and the linked list-based implementation are identical – The client interacts with the stack in the same way, regardless of implementation – We can replace the data structure and implementation, and the client will notice at all (in most cases) October 26, 2020 Hassan Khosravi / Geoffrey Tien 8

Queue ADT October 26, 2020 Hassan Khosravi / Geoffrey Tien 9

Queue ADT October 26, 2020 Hassan Khosravi / Geoffrey Tien 9

Queues • October 26, 2020 Hassan Khosravi / Geoffrey Tien 10

Queues • October 26, 2020 Hassan Khosravi / Geoffrey Tien 10

Queue applications • • Holding printer jobs CPU job scheduling Database requests Packet routing

Queue applications • • Holding printer jobs CPU job scheduling Database requests Packet routing for a messaging server Course waitlists Network searching (breadth-first search). . . October 26, 2020 Hassan Khosravi / Geoffrey Tien 11

Queue ADT • Queue ADT should support at least the first two operations: –

Queue ADT • Queue ADT should support at least the first two operations: – – – enqueue – insert an item to the back of the queue dequeue – remove an item from the front of the queue peek – return the element at the front of the queue is. Empty – does the queue contain any items initialization, etc. • The Queue ADT is completely described by the above behaviour – a client using the queue only needs to understand how to call the functions – like the stack, queue ADT can be implemented using different data structures, transparently to client code October 26, 2020 Hassan Khosravi / Geoffrey Tien 12

Queue implementation Using an array • enqueue 8 dequeue myqueue front 2 1 -1

Queue implementation Using an array • enqueue 8 dequeue myqueue front 2 1 -1 0 back 4 5 capacity 6 arr October 26, 2020 4 7 3 1 6 Hassan Khosravi / Geoffrey Tien 8 Problem? 13

Circular arrays • Trick: use a circular array to insert and remove items from

Circular arrays • Trick: use a circular array to insert and remove items from a queue in constant time • The idea of a circular array is that the end of the array “wraps around” to the start of the array 7 0 6 0 1 2 3 4 5 6 7 1 2 5 4 October 26, 2020 Hassan Khosravi / Geoffrey Tien 3 14

The modulo operator • The mod operator (%) calculates remainders: – 1%5 = 1,

The modulo operator • The mod operator (%) calculates remainders: – 1%5 = 1, 2%5 = 2, 5%5 = 0, 8%5 = 3 • The mod operator can be used to calculate the front and back positions in a circular array – Thereby avoiding comparisons to the array size – The back of the queue is: • (front + num) % capacity • where num is the number of items in the queue – After removing an item, the front of the queue is: • (front + 1) % capacity October 26, 2020 Hassan Khosravi / Geoffrey Tien typedef struct { int front; int num; int capacity; int* arr; } Queue; 15

Queue implementation Using an array typedef struct { int front; int num; int capacity;

Queue implementation Using an array typedef struct { int front; int num; int capacity; int* arr; } Queue; void initialize(Queue* q) { q->front = 0; q->num = 0; q->capacity = 6; // or some other value q->arr = (int*) malloc(q->capacity * sizeof(int)); } int is. Empty(Queue* q) { if (q->num == 0) return TRUE; else return FALSE; } October 26, 2020 int is. Full(Queue* q) { if (q->num == q->capacity) return TRUE; else return FALSE; } Hassan Khosravi / Geoffrey Tien 16

Queue implementation Using an array int enqueue(Queue* q, int val) { if (is. Full(q))

Queue implementation Using an array int enqueue(Queue* q, int val) { if (is. Full(q)) return FALSE; else { q->arr[(q->front + q->num) % q->capacity] = val; q->num++; return TRUE; } } int dequeue(Queue* q) { if (is. Empty(q)) return FALSE; else { q->arr[q->front] = -1; q->front = (q->front + 1) % q->capacity; q->num--; return TRUE; } } October 26, 2020 Hassan Khosravi / Geoffrey Tien 17

Array queue example Queue myq; initialize(&myq); 0 01 front num enqueue(&myq, 6); 6 0

Array queue example Queue myq; initialize(&myq); 0 01 front num enqueue(&myq, 6); 6 0 1 2 3 4 5 Insert item at (front + num) % capacity, then increment num October 26, 2020 Hassan Khosravi / Geoffrey Tien 18

Array queue example Queue myq; initialize(&myq); 210 345 front num enqueue(&myq, 6); enqueue(&myq, dequeue(&myq);

Array queue example Queue myq; initialize(&myq); 210 345 front num enqueue(&myq, 6); enqueue(&myq, dequeue(&myq); October 26, 2020 4); 7); 3); 8); 6 4 7 3 8 0 1 2 3 4 5 Insert item at (front + num) % capacity, then increment num Remove item at front, then decrement num and make front = (front + 1) % capacity Hassan Khosravi / Geoffrey Tien 19

Array queue example Queue myq; initialize(&myq); 2 543 front num enqueue(&myq, 6); enqueue(&myq, 4);

Array queue example Queue myq; initialize(&myq); 2 543 front num enqueue(&myq, 6); enqueue(&myq, 4); 7); 3); 8); dequeue(&myq); enqueue(&myq, 9); 5 0 1 7 3 8 9 2 3 4 5 Insert item at (front + num) % capacity, then increment num Remove item at front, then decrement num and make front = (front + 1) % capacity enqueue(&myq, 5); enqueue is possible as long as the array is not full October 26, 2020 Hassan Khosravi / Geoffrey Tien 20

Array queue resizing • Suppose we have an array-based queue with (theoretically) unlimited enqueueing

Array queue resizing • Suppose we have an array-based queue with (theoretically) unlimited enqueueing and we have performed some enqueue and dequeue operations – Then we perform more enqueues to fill the array – How should we resize the array to allow for more enqueue operations? 12 5 76 33 2 41 ? ? front ? October 26, 2020 ? ? ? Hassan Khosravi / Geoffrey Tien ? ? 21

Queue implementation Using a linked list • Removing items from the front of the

Queue implementation Using a linked list • Removing items from the front of the queue is straightforward • Items should be inserted at the back of the queue in constant time – So we must avoid traversing through the list – Use a back pointer! typedef struct { struct Node* front; struct Node* back; int num; } Queue; struct Node { int data; struct Node* next; }; void initialize(Queue* q) { q->front = NULL; q->back = NULL; q->num = 0; } October 26, 2020 int is. Empty(Queue* q) { if (q->front == NULL) return TRUE; else return FALSE; } Hassan Khosravi / Geoffrey Tien 22

Queue implementation int enqueue(Queue* q, int val) { struct Node* newnode = (struct Node*)

Queue implementation int enqueue(Queue* q, int val) { struct Node* newnode = (struct Node*) malloc(sizeof(struct Node)); if (q->front == NULL) { // special case: empty list q->front = newnode; q->back = newnode; int dequeue(Queue* q) { } struct Node* temp = front; else { // general case if (is. Empty(q)) q->back->next = newnode; return FALSE; q->back = newnode; else { } q->front = q->front->next; q->num++; free(temp); return TRUE; temp = NULL; } q->num--; int peek(Queue* q) { if (is. Empty(q)) q->back = NULL; return FALSE; return TRUE; else } return q->front->data; } } October 26, 2020 Hassan Khosravi / Geoffrey Tien 23

List queue example Queue myq; init. Queue(&myq); enqueue(&myq, 6); front 6 back 4 enqueue(&myq,

List queue example Queue myq; init. Queue(&myq); enqueue(&myq, 6); front 6 back 4 enqueue(&myq, 4); enqueue(&myq, 7); enqueue(&myq, 3); 7 dequeue(&myq); 3 October 26, 2020 Hassan Khosravi / Geoffrey Tien 24

Exercise • For the array-based queue, write the enqueue function to support array resizing!

Exercise • For the array-based queue, write the enqueue function to support array resizing! – See the array resizing stack example for reference, but be aware of the issues mentioned in slide #24 October 26, 2020 Hassan Khosravi / Geoffrey Tien 25

Readings for this lesson • Thareja – Chapter 8. 1 – 8. 3, 8.

Readings for this lesson • Thareja – Chapter 8. 1 – 8. 3, 8. 5 (Queues) • Next class – Thareja Chapter 7. 7. 4 (Recursion) October 26, 2020 Hassan Khosravi / Geoffrey Tien 26