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

Essential 4

The document provides an overview of queue data structures, including their implementations in C++ and the Standard Template Library (STL). It also covers double-ended queues (deques), priority queues, and their applications in various algorithms and real-world scenarios. Additionally, the document introduces trees, specifically binary trees and binary search trees, detailing their properties, implementations, and applications.

Uploaded by

rohy1990
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)
10 views11 pages

Essential 4

The document provides an overview of queue data structures, including their implementations in C++ and the Standard Template Library (STL). It also covers double-ended queues (deques), priority queues, and their applications in various algorithms and real-world scenarios. Additionally, the document introduces trees, specifically binary trees and binary search trees, detailing their properties, implementations, and applications.

Uploaded by

rohy1990
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/ 11

39

private:
Node *front, *rear;

public:
Queue() : front(nullptr), rear(nullptr) {}

void enqueue(int value) {


Node* newNode = new Node{value, nullptr};
if (rear == nullptr) {
front = rear = newNode;
return;
}
rear->next = newNode;
rear = newNode;
}

void dequeue() {
if (front == nullptr) {
std::cout << "Queue Underflow\n";
return;
}
Node* temp = front;
front = front->next;
if (front == nullptr) rear = nullptr; // Reset rear if queue
,→ becomes empty
delete temp;
}

int peek() {
if (front == nullptr) {
std::cout << "Queue is Empty\n";
return -1;
40

}
return front->data;
}

bool isEmpty() {
return front == nullptr;
}

void display() {
Node* temp = front;
while (temp != nullptr) {
std::cout << temp->data << " ";
temp = temp->next;
}
std::cout << "\n";
}

˜Queue() {
while (front != nullptr) {
dequeue();
}
}
};

int main() {
Queue q;
q.enqueue(10);
q.enqueue(20);
q.enqueue(30);

q.display();
q.dequeue();
41

q.display();

return 0;
}

Using STL
The std::queue container in STL simplifies queue implementation.

Code Example:

#include <iostream>
#include <queue>

int main() {
std::queue<int> q;

q.push(10);
q.push(20);
q.push(30);

std::cout << "Front element: " << q.front() << "\n";

q.pop();
std::cout << "After dequeue, front element: " << q.front() << "\n";

std::cout << "Elements in queue: ";


while (!q.empty()) {
std::cout << q.front() << " ";
q.pop();
}
std::cout << "\n";
42

return 0;
}

Double-Ended Queue (Deque)


A double-ended queue allows insertion and deletion at both ends. In C++, std::deque is a
powerful implementation that supports random access.

Code Example:

#include <iostream>
#include <deque>

int main() {
std::deque<int> dq;

dq.push_back(10);
dq.push_front(20);
dq.push_back(30);

std::cout << "Front element: " << dq.front() << "\n";


std::cout << "Back element: " << dq.back() << "\n";

dq.pop_front();
dq.pop_back();

std::cout << "Elements in deque: ";


for (int elem : dq) {
std::cout << elem << " ";
}
std::cout << "\n";
43

return 0;
}

Priority Queue
A priority queue stores elements based on their priority rather than insertion order. In C++,
std::priority queue uses a max-heap by default.
Code Example:

#include <iostream>
#include <queue>
#include <vector>

int main() {
std::priority_queue<int> pq;

pq.push(30);
pq.push(10);
pq.push(20);

std::cout << "Top element: " << pq.top() << "\n";

pq.pop();
std::cout << "After pop, top element: " << pq.top() << "\n";

std::cout << "Elements in priority queue: ";


while (!pq.empty()) {
std::cout << pq.top() << " ";
pq.pop();
}
std::cout << "\n";
44

return 0;
}

To create a min-heap, use a custom comparator:

std::priority_queue<int, std::vector<int>, std::greater<int>> minHeap;

4.3 Applications of Queues


1. Task Scheduling Queues are used in operating systems to manage processes in a FIFO
order.

2. Breadth-First Search (BFS)


Queues are essential in graph traversal algorithms like BFS.

3. Data Stream Management Buffers in data streaming services often rely on queues.

4. Deques in Palindrome Checking Deques are used to check palindromes efficiently.

5. Priority Queue in Pathfinding Priority queues are critical in algorithms like Dijkstra's
for shortest path computation.

Conclusion
Queues and their variants (Deque, Priority Queue) play a vital role in solving real-world
problems efficiently. Mastering their implementation and applications enhances your C++
programming skills and prepares you for advanced concepts. This chapter lays the foundation
for understanding more complex data structures like trees and graphs, covered in upcoming
chapters.
Chapter 5

Trees

Trees are a fundamental data structure in computer science, representing hierarchical


relationships between elements. Unlike linear data structures such as arrays, linked lists, stacks,
or queues, trees allow for efficient storage, retrieval, and manipulation of data in non-linear
formats. In this chapter, we delve into the most common types of trees: binary trees, binary
search trees (BST), balanced trees (like AVL and Red-Black Trees), and segment trees. Each
section includes explanations, implementations in C++, and real-world applications.

5.1 What is a Tree?


A tree is a hierarchical data structure consisting of nodes, where one node is designated as the
root, and all other nodes are connected by edges to form a parent-child relationship.
Key Characteristics of Trees:

• Root Node: The topmost node in the hierarchy.

• Parent and Child Nodes: A parent node has one or more children connected via edges.

45
46

• Leaf Nodes: Nodes without any children.

• Height: The longest path from the root node to any leaf node.

• Trees are acyclic (no loops) and connected.

5.2 Binary Trees


A binary tree is a tree where each node has at most two children, referred to as the left and right
child.

Definition and Properties

• Binary trees are widely used for search operations and data representation.

• The two subtrees (left and right) of a node are themselves binary trees.

Applications:

• Representing hierarchical data like XML/HTML parsing.

• Storing data in efficient formats for retrieval, such as Huffman Encoding.

Binary Tree Implementation


Code Example:

#include <iostream>
using namespace std;

struct Node {
int data;
47

Node* left;
Node* right;

Node(int value) : data(value), left(nullptr), right(nullptr) {}


};

class BinaryTree {
public:
Node* root;

BinaryTree() : root(nullptr) {}

void preorder(Node* node) {


if (node == nullptr) return;
cout << node->data << " ";
preorder(node->left);
preorder(node->right);
}

void inorder(Node* node) {


if (node == nullptr) return;
inorder(node->left);
cout << node->data << " ";
inorder(node->right);
}

void postorder(Node* node) {


if (node == nullptr) return;
postorder(node->left);
postorder(node->right);
cout << node->data << " ";
}
48

};

int main() {
BinaryTree tree;
tree.root = new Node(1);
tree.root->left = new Node(2);
tree.root->right = new Node(3);
tree.root->left->left = new Node(4);
tree.root->left->right = new Node(5);

cout << "Inorder Traversal: ";


tree.inorder(tree.root);
cout << "\n";

return 0;
}

5.3 Binary Search Trees (BST)


A binary search tree is a special binary tree where the left child of a node contains values smaller
than the parent, and the right child contains values greater than the parent.

Properties

• Allows efficient searching, insertion, and deletion operations.

• Time complexity:

– Average case: O(logn)O(\log n)O(logn).

– Worst case: O(n)O(n)O(n) (unbalanced tree).


49

Implementation of BST
Code Example:

struct BSTNode {
int data;
BSTNode* left;
BSTNode* right;

BSTNode(int value) : data(value), left(nullptr), right(nullptr) {}


};

class BST {
private:
BSTNode* insert(BSTNode* node, int value) {
if (node == nullptr) return new BSTNode(value);
if (value < node->data)
node->left = insert(node->left, value);
else
node->right = insert(node->right, value);
return node;
}

void inorderTraversal(BSTNode* node) {


if (node == nullptr) return;
inorderTraversal(node->left);
cout << node->data << " ";
inorderTraversal(node->right);
}

public:
BSTNode* root;

BST() : root(nullptr) {}

You might also like