0% found this document useful (0 votes)
2 views

CS 13

This document is a lecture on programming concepts in C++, focusing on arrays, queues, and stacks. It explains the implementation and utility of queues (FIFO) and stacks (LIFO) in programming, providing examples such as a taxi stand and palindrome checking. Additionally, it includes exercises for enhancing understanding of stack operations and their applications in undo/redo functionality.

Uploaded by

soham.work08
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

CS 13

This document is a lecture on programming concepts in C++, focusing on arrays, queues, and stacks. It explains the implementation and utility of queues (FIFO) and stacks (LIFO) in programming, providing examples such as a taxi stand and palindrome checking. Additionally, it includes exercises for enhancing understanding of stack operations and their applications in undo/redo functionality.

Uploaded by

soham.work08
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 13

AN INTRODUCTION TO PROGRAMMING

THROUGH C++

with
Manoj Prabhakaran

Lecture 13
Arrays (ctd.)
Queues and Stacks

Based on material developed by Prof. Abhiram G. Ranade


Recap
¥ (C-style) Arrays
¥ A few examples: Counters, storing text elements for use later
(palindrome), sorting
¥ Restrictions of C-style arrays: Need to fix the size at compile time,
cannot pass by value or return from functions, somewhat unusual syntax
for the type declaration
Today
¥ Using arrays as Data Structures
¥ To keep data in ways convenient for various tasks/algorithms
¥ Queues and Stacks
¥ Today: Implementing queues and stacks. Using them in examples.
Queue
¥ When people form a queue:
¥ People join and leave the queue
¥ You have to join the queue at the "back"
¥ You leave the queue only after you reach the "front"
¥ Items leave the queue in the order in which they join
¥ First In First Out (FIFO)
¥ Why are queues useful in programs?
¥ Storing items (e.g. key presses, mouse clicks, network packets) until they
are processed one-by-one
¥ Systematic searches (e.g., for a short path in a maze) often use a queue
Example: Taxi Stand

¥ Taxis arrive and stand in a queue


¥ A customer, on arriving, gets into the taxi at the front of the queue
¥ If a customer arrives when the taxi stand is empty, they leave
¥ If a taxi arrives when the taxi stand is full, it leaves
¥ A program that tracks the status of the taxi stand:
¥ Accept inputs of the form "taxi" (includes, say, the vehicle number)
and of the form "customer" (includes, say, the destination)
¥ Print out (taxi,customer) pairings, or error messages (customer not
accommodated, or taxi not accommodated)
Example: Taxi Stand
struct taxi { string id; void read(); };
struct customer { string dest; void read(); };
struct taxiQueue {
taxiQueue tq; tq.clear(); /* members to be filled in */
void clear(); bool enqueue (const taxi&); bool dequeue (taxi&);
for(...) { };
... void assign(const taxi&, const customer&);
if (input == 'T') {
taxi t; t.read();
bool ok = tq.enqueue(t); // returns true if succeeded
if (!ok) cerr << "Could not add taxi " << t.id << endl;
} else if (input == 'C') {
taxi t; customer c; c.read();
bool ok = tq.dequeue(t); // returns true if succeeded
if(ok) assign(t,c);
else cerr << "Could not find a taxi for " << c.dest << endl;
}
}
const int qCapacity = 6; Example: Taxi Stand
struct taxiQueue { begin
taxi Q[qCapacity]; int begin, end; // members
void clear(); bool enqueue(const taxi&); bool dequeue(taxi&);
};
void taxiQueue::clear () { begin = end = 0; }
bool taxiQueue::enqueue (const taxi& t) {
end
/* fill in at Q[end], and increment end */
enqueue
} Our queue's enqueue
bool taxiQueue::dequeue (taxi& t) { capacity is reducing enqueue
with each dequeue! dequeue
/* remove from Q[begin], and increment begin */ enqueue
Move data so that
begin is always 0? dequeue
} (That is what real dequeue
dequeue
Invariant: taxis will do!)
Queue elements stored in Q[begin],É,Q[end-1].
Q[begin] is the first occupied slot, Q[end] is the first empty slot. Moving data can be
Unless queue is empty: Then begin == end. slowÉ
const int qCapacity = 6; Example: Taxi Stand Demo
struct taxiQueue {
taxi Q[qCapacity]; int begin, end; bool full; // members begin
void clear(); bool enqueue(const taxi&); bool dequeue(taxi&);
};
void taxiQueue::clear () { begin = end = 0; full = false;}
bool taxiQueue::enqueue (const taxi& t) { 0
if(full) return false; begin==end can 5 1
mean empty or full
end
Q[end] = t; // copy to the end of the queue
end = (end+1) % qCapacity; // advance end clockwise 4 2
if (end == begin) full = true; 3
return true;
}
bool taxiQueue::dequeue (taxi& t) {
if (end == begin && !full) return false;
t = Q[begin]; // copy the front element into t
full
begin = (begin+1) % qCapacity; // advance begin clockwise
full = false; // never full after dequeuing
return true;
}
Stack
¥ Recall what a stack is:
¥ Objects (say books) are kept one on top of the other
¥ An item can be added only to the top of the stack
¥ Can remove only the top-most item (the most recently added)
¥ Last-In First-Out (LIFO)
¥ Why are stacks useful in programs?
¥ Already saw: Memory allocated for function calls naturally use a stack (last
function invoked is the first to return)
¥ Systematic searches often use a stack too
¥ To support "undo", a stack can used to store actions so far
¥ É
A Simple Stack Implementation
const int stCap = 1000; // capacity
struct charStack {
char St[stCap];
int top; // top = -1 for empty stack
bool pop(char& i) { // if stack is empty, return false
if (top == -1) return false;
i = St[top--];
2 c top
return true;
} 1 b

bool push(char i) { // if stack is full, return false 0 a


if (top == stCap-1) return false;
-1
St[++top] = i;
return true;
}
void clear() { top = -1; }
};
Example: Palindrome using a Stack
¥ Needed the array only as a stack
int main() {
charStack st; st.clear();
char x, y;
int n; cin >> n;
for (int i=0; i<n/2; i++)
if(cin >> x, !st.push(x)) {cerr << "Stack overflow!\n"; return -1; }
if (n%2) cin >> x; // if n odd, ignore the middle character
for (int i=n/2-1; i>=0; i--) { // compare stored characters with rest
if (cin >> x, st.pop(y), x != y) {
cout << "Not a palindrome!" << endl; return 1;
}
}
cout << "Palindrome!" << endl;
}
Example: Undo Stack
bool docommand(char c, charStack& history); // pushes command into history
bool undo(charStack& history);
int main() {
turtleSim();
cout << "Enter f/r/l for forward/right/left, u to undo, q to quit: ";
charStack history; history.clear();
char input;
for(cin >> input; !cin.fail(); cin >> input) {
if(input == 'q')
break;
else if (input == 'u')
if(!undo(history)) // pop history stack and reverse the popped comand
cerr << "Undo stack empty!\n";
else if (!docommand(input,history))
cerr << "Ignoring unrecognized command" << endl;
}
}
Example: Undo Stack Demo
bool docommand(char c, charStack& history) {
if (c == 'f' || c == 'r' || c == 'l') {
history.push(c) || (history.clear(), history.push(c));
if (c == 'f') forward(10);
else if (c == 'r') right(90); If push failed, clear history and push again.
else /* (c == 'l') */ left(90);
return true;
} bool undo(charStack& history) {
return false; char c;
} if(!history.pop(c)) {
return false;
} else {
if (c == 'f') forward(-10);
else if (c == 'r') right(-90);
else /* (c == 'l') */ left(-90);
return true;
}
}
Exercises
¥ Use two stacks to ¥ Implement a stack
allow undo and redo. structure which
forgets the oldest
Note that the redo item when an item is
stack gets cleared pushed into a full
whenever any valid stack. Use it as the
command other than undo stack.
undo/redo is
executed Hint: Try a "circular stack"

You might also like