0% found this document useful (0 votes)
10 views40 pages

Stacks and Queues Lecture

The document provides an overview of stack and queue data structures, emphasizing their LIFO and FIFO principles, respectively. It details operations such as push, pop, and peek for stacks, and enqueue and dequeue for queues, along with their time complexities. Additionally, it discusses implementations using arrays and linked lists, common pitfalls, and provides examples of standard library methods for both stacks and queues.

Uploaded by

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

Stacks and Queues Lecture

The document provides an overview of stack and queue data structures, emphasizing their LIFO and FIFO principles, respectively. It details operations such as push, pop, and peek for stacks, and enqueue and dequeue for queues, along with their time complexities. Additionally, it discusses implementations using arrays and linked lists, common pitfalls, and provides examples of standard library methods for both stacks and queues.

Uploaded by

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

Stacks

Introduction To Stack

Stack data structure is a linear data structure that accompanies a principle


known as LIFO (Last In First Out) or FILO (First In Last Out).
Real Life Example

Stack of plates Stack of books


Stack Operations

Push operation
● Add an element to the top of the stack
Stack Operations
Stack Operations
Stack Operations
Stack Operations

Pop operation
● Remove element from the top of the stack
Stack Operations
Stack Operations
Stack Operations

Top
Peek operation
● returning the top element of a stack.

Is empty()
● Check if the list is empty or not.
● If it’s empty return True else False.
Implementation
#include <vector>
#include <stdexcept>
#include <iostream>
int top() const {
class Stack { if (data.empty()) {
private: throw
std::vector<int> data; std::out_of_range("top() called on
public:
empty stack");
Stack() {}; }
return data.back();
void push(int x) { }
data.push_back(x);
}
bool empty() const {
int pop() { return data.empty();
if (data.empty()) {
}
throw std::out_of_range("pop() called on
empty stack"); };
}
int val = data.back();
data.pop_back();
return val;
}
Can we implement Stack with a
different data structure?
Implementing stack using linked list
Push operation
● Initialise a node

● Update the value of that node by data i.e. node.value = data


● Now link this node to the top of the linked list i.e. node.next = head
● And update top pointer to the current node i.e. head = node
POP operation
● First Check whether there is any node present in the linked list or not, if not then return

● Otherwise make pointer let say temp to the top node and move forward the top node by 1
step
● Now free this temp node

Removed node
Top operation
● Check if there is any node present or not, if not then return.

● Otherwise return the value of top node of the linked list which is the node at Head
Implementation
#include <stdexcept>

struct Node { / Return the top element without removing it


int data; // Throws std::out_of_range if the stack is empty
Node* next; int peek() const {
Node(int data) : data(data), next(nullptr) {} if (isempty()) {
}; throw std::out_of_range("peek() called on empty stack");
}
return head->data;
class Stack {
}
private:
Node* head; // Push a new element onto the stack
void push(int data) {
public: Node* new_node = new Node(data);
// Constructor new_node->next = head;
Stack() : head(nullptr) {} head = new_node;
}

// Destructor to clean up any remaining nodes // Pop the top element off the stack and return its value
~Stack() { // Throws std::out_of_range if the stack is empty
while (head) { int pop() {
Node* tmp = head; if (isempty()) {
head = head->next; throw std::out_of_range("pop() called on empty stack");
delete tmp; }
Node* popped_node = head;
}
int value = popped_node->data;
} head = head->next;
delete popped_node;
// Check whether the stack is empty return value;
bool isempty() const { }
return head == nullptr; };
}

/
Time and space complexity

● Push
○ Time complexity - ___?
● Pop
○ Time complexity - ___?
● Peek
○ Time complexity - ___?
● isEmpty()
○ Time complexity - ___?
Time and space complexity

● Push
○ Time complexity - O(1)
● Pop
○ Time complexity - O(1)
● Peek
○ Time complexity - O(1)
● isEmpty()
○ Time complexity - O(1)
Applications of Stack
Reflection: Stack can help you simulate deletion of
elements in the middle in O(1) time complexity

22
Reflection: stack can help you defer decision
until some tasks are finished.

The bottom of the stack waits on the top of stack


until they are processed

23
Common PitFalls

● Popping from empty list


○ This will throw index out of range error
● Null pointer exception if we are using linked list
Common PitFalls

● Stack overflow

○ Pushing to a full stack


Queues
Introduction

A collection whose elements are added at one end (the rear) and
removed from the other end (the front)

● Uses FIFO data handling


Real Life Example
Queue Operations

Enqueue (Append)
● Add an element to the tail of a queue

● First In
Queue Operations

Dequeue (Popleft)
● Remove an element from the head of the queue

● First Out
Implementing Queue

Using an array to implement a queue is significantly harder than using


an array to implement a stack. Why?

What would the time complexity be?


Implementing Queue with List
#include <vector>

class Queue {
std::vector<int> queue;
int headIndex;
public:
Queue(int k) : headIndex(0) {}
void append(int value) {
queue.push_back(value);
}
int pop() {
if (headIndex < queue.size()) {
int val = queue[headIndex];
headIndex++;
return val;
}
}
};
Implementing Queue

● Either linked list or list can be used with careful considerations

● In practice, prefer to use built-in or library implementations like

deque()
● Internally, deque() is implemented as a linked list of nodes
.pop()
.append()
.popleft()
.appendleft()
Time and space complexity

● Append
○ Time complexity - ____?

● Pop
○ Time complexity - ____?

● Peek
○ Time complexity - ____?

● isEmpty()
○ Time complexity - ____?
Time and space complexity

● Append
○ Time complexity - O(1)

● Pop
○ Time complexity - O(1)

● Peek
○ Time complexity - O(1)

● isEmpty()
○ Time complexity - O(1)
Stack Overview

Header:
🔹 std::stack<T> – Key Methods
🔹 #include <stack>

Method Description Example

push(val) Adds element to top st.push(10);

pop() Removes top element (no st.pop();


return)
top() Access top element st.top();

empty() Checks if stack is empty st.empty()

size() Number of elements st.size();


Queue Overview

Header:
🔹 std::queue<T>
🔹 #include <queue>

Method Description Example

push(val) Adds element to the back of queue q.push(10);

pop() Removes element from the front q.pop();

front() Returns reference to the front element int x = q.front();

back() Returns reference to the back element int x = q.back();

empty() Returns true if queue is empty q.empty()

size() Returns number of elements in queue q.size()


Hashmap Overview
Header:
🔹 #include <unordered_map>

Method Description Example

map[key] Access or insert a value by key map['a'] = 1;

at(key) Access value (throws exception if key not map.at('a');


found)

count(key) Returns 1 if key exists, 0 if not if (map.count(')'))

find(key) Returns iterator to key or map.end() if not found if (map.find(')') != map.end())

insert({key, value}) Inserts a key-value pair map.insert({'x', 42});

erase(key) Removes key and its value map.erase('x');

clear() Removes all elements map.clear();


Practice Problems

Implement Queue using Stacks - LeetCode


Implement Stack using Queues - LeetCode
Valid Parentheses - LeetCode
Evaluate Reverse Polish Notation - LeetCode

You might also like