My Take on UCSD's Basic Data Structures course (CSE 12)
Stacks and Queues are ADTs that represent some of the most normally occurring phenomena we see in day to day life.
Examples include:
Firstly, we’ll talk about stacks.
What: ADT that supports three basic operations: push
, pop
, and top/peek
Why: Provides constant time $O(1)$ access to only the most recently added element. Allows us to create a history of things in order that they were seen. Follows ordering of Last in, First Out (LIFO).
Let’s give some practical coding examples for stacks!
Q: Given a string, return true
if the string has balanced symbols and false
otherwise.
Examples:
”([{}])” –> true
“(hello there)” –> true
”{[}]” –> false
“General Kenobi” –> true
How would you approach this question? Discuss
Solution:
Create a stack. Read characters in. If you see a ‘(‘, ‘[’, or a ‘{‘, push it onto the stack. When you see one of the closing ones, pop off of the stack and check if you have a matching pair. Once you’re done reading the string, check if your stack is empty and return true
if so. This runs in $O(n)$ time where n
is the length of the string.
Q: How do you turn something like 1 + 2 * 3 - (4 + 5) into the equivalent postfix?
Examples:
1 + 2 * 3 - (4 + 5) –> 1 2 3 * + 4 5 + -
Solution:
I’ll let you think about this one :)
Next, queues. Queues are known as First in, First out structures (FIFOs), and have many applications from normal waiting to process scheduling by the operating system.
Queues support enqueue
(add an item) and dequeue
(remove an item) operations.
Queues can be implemented worst case to take linear time for both operations, but it is possible to get constant time enqueue
and dequeue
. How might we do this?
Pros:
Cons:
How do we use them?
#ifndef STACK_HPP
#define STACK_HPP
#include <iostream>
#include <vector>
template <class T>
class stack {
private:
std::vector<T> *vec; // The stack itself
public:
stack(void) {
this->vec = new std::vector<T>();
}
~stack(void) {
delete this->vec;
}
bool empty(void); // Check if empty
size_t size(void) const; // Get size of stack
T & top(void) const; // Get element at top of stack
void pop(void); // Remove element from top of stack
void push(T &); // Insert element at top of stack
}
template <class T>
bool stack<T>::empty(void) {
return this->vec->size();
}
.
.
.
#endif
Some notes:
.cpp
file, you’ll need an #include <filename>.cpp
right above the #endif
.template <class classname>
above it.stack<int> s;
to invoke the constructor.Now, for iterators
for-each
loops (for(auto a : structure) { ... }
)operator ++
It’s a bit complex, so I’ll differ this to your own research.
That’s all folks! Next time, Linked Lists