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

DSA Notes

The document provides an overview of various programming concepts in C++, including arrays, strings, functions, pointers, and classes. It explains the definitions, uses, and examples of one-dimensional and two-dimensional arrays, string manipulation functions, function declarations, calls, and definitions, as well as memory allocation types. Additionally, it covers the fundamentals of classes and objects, highlighting their characteristics and importance in Object-Oriented Programming.

Uploaded by

24250156maithri
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)
5 views

DSA Notes

The document provides an overview of various programming concepts in C++, including arrays, strings, functions, pointers, and classes. It explains the definitions, uses, and examples of one-dimensional and two-dimensional arrays, string manipulation functions, function declarations, calls, and definitions, as well as memory allocation types. Additionally, it covers the fundamentals of classes and objects, highlighting their characteristics and importance in Object-Oriented Programming.

Uploaded by

24250156maithri
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/ 49

Array

1. 1D Array:
o A one-dimensional array is a collection of data items that are
stored in contiguous memory locations, typically used to store a
list of elements of the same data type. The elements are accessed
using a single index.
o Example: int arr[5] = {1, 2, 3, 4, 5};
2. 2D Array:
o A two-dimensional array is an array of arrays. It's used to store
data in a matrix form where elements are accessed using two
indices (row and column).
o Example: int matrix[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}.

Strings
1. strlen (String Length)
The strlen function returns the length of a C-style string (a character array),
excluding the null terminator (\0).
Explanation:
• We declare a character array str[] initialized with "Hello World".
• We use strlen(str) to get the length of the string, which counts all
characters except for the null terminator at the end.
• The result is then printed using cout.
Example:
#include <iostream>
#include <cstring> // For strlen

int main() {
char str[] = "Hello World";
int length = strlen(str); // Calculates the length of the string
cout << "Length of the string: " << length << endl; // Output: 11
return 0;
}

2. strcat (String Concatenation)


The strcat function appends one C-style string (character array) to another.
Explanation:
• We declare two character arrays str1 and str2.
• str1 has extra space to accommodate str2 because concatenation
needs enough room for both strings and the null terminator.
• strcat(str1, str2) concatenates str2 to str1. The resulting string is stored
in str1.
• We then print the concatenated result.
Example:
#include <iostream>
#include <cstring> // For strcat

int main() {
char str1[20] = "Hello"; // str1 has extra space for concatenation
char str2[] = " World";

strcat(str1, str2); // Appends str2 to str1


cout << "Concatenated string: " << str1 << endl; // Output: Hello World

return 0;
}

3. strcpy (String Copy)


The strcpy function copies one C-style string (character array) to another.
Explanation:
• We declare a source string source[] and a destination string
destination[].
• The destination string must have enough space to hold the contents of
the source string.
• strcpy(destination, source) copies the contents of source to
destination.
• We print the copied string from destination.
Example:
#include <iostream>
#include <cstring> // For strcpy

int main() {
char source[] = "Hello";
char destination[20]; // Destination array has enough space

strcpy(destination, source); // Copies the content of source to destination


cout << "Copied string: " << destination << endl; // Output: Hello

return 0;
}

4. strrev (String Reverse)


C++ does not have a built-in strrev function, so we write our own function to
reverse a string.

Explanation:
• The reverseString() function uses a loop to swap the characters at the
start and end of the string, gradually moving towards the middle.
• The length of the string is calculated using strlen(str).
• Once the string is reversed, the function terminates, and we print the
reversed string.
Example:
#include <iostream>
#include <cstring> // For strlen

void reverseString(char str[]) {


int len = strlen(str); // Find the length of the string
for (int i = 0; i < len / 2; i++) {
// Swap the characters at i and (len - i - 1)
char temp = str[i];
str[i] = str[len - i - 1];
str[len - i - 1] = temp;
}
}

int main() {
char str[] = "Hello";

reverseString(str); // Reverses the string


cout << "Reversed string: " << str << endl; // Output: olleH

return 0;
}
5. strupr (Convert to Uppercase)
C++ does not have a built-in strupr function, but we can convert each
character to uppercase using the toupper function.
Explanation:
• The toUppercase() function iterates through the string and uses
toupper() to convert each character to uppercase.
• toupper() is part of the <cctype> library and converts a character to its
uppercase equivalent.
• After conversion, the modified string is printed.
Example:
#include <iostream>
#include <cctype> // For toupper

void toUppercase(char str[]) {


for (int i = 0; str[i] != '\0'; i++) {
str[i] = toupper(str[i]); // Convert each character to uppercase
}
}

int main() {
char str[] = "hello";
toUppercase(str); // Converts the string to uppercase
cout << "Uppercase string: " << str << endl; // Output: HELLO
return 0;
}
6. strlwr (Convert to Lowercase)
Similar to strupr, C++ does not have a strlwr function, but we can convert each
character to lowercase using tolower.
Explanation:
• The toLowercase() function iterates through the string and uses
tolower() to convert each character to lowercase.
• tolower() is part of the <cctype> library and converts a character to its
lowercase equivalent.
• After conversion, the modified string is printed.
Example:
#include <iostream>
#include <cctype> // For tolower

void toLowercase(char str[]) {


for (int i = 0; str[i] != '\0'; i++) {
str[i] = tolower(str[i]); // Convert each character to lowercase
}
}

int main() {
char str[] = "HELLO";
toLowercase(str); // Converts the string to lowercase
cout << "Lowercase string: " << str << endl; // Output: hello
return 0;
}
7. strcmp (String Comparison)
The strcmp function compares two C-style strings lexicographically. It returns:
• 0 if the strings are equal.
• A positive value if the first string is greater than the second.
• A negative value if the second string is greater than the first.
Explanation:
• We declare two-character arrays str1[] and str2[] for comparison.
• strcmp(str1, str2) compares the strings and returns an integer value
based on the lexicographical order.
• We check the result and print whether the strings are equal, or if one is
greater than the other.
Example:
#include <iostream>
#include <cstring> // For strcmp

int main() {
char str1[] = "Hello";
char str2[] = "World";

int result = strcmp(str1, str2); // Compare str1 and str2

if (result == 0) {
cout << "Strings are equal" << endl;
} else if (result > 0) {
cout << "String 1 is greater" << endl;
} else {
cout << "String 2 is greater" << endl;
}

return 0;
}

Functions

1. Function Declaration (or Function Prototype)


A function declaration tells the compiler about the function's name, return
type, and parameters (if any) without providing the actual body
(implementation) of the function. This allows the function to be called in the
code before it is defined later.
Syntax:
return_type function_name(parameter_list);
• Return type: Specifies what type of value the function will return (e.g.,
int, float, void).
• Function name: The identifier by which the function is called.
• Parameter list: Optional; specifies the type and number of parameters
the function accepts.
Example:
int add(int a, int b); // Function declaration
Here, add is the function name, it returns an int type, and it takes two integer
parameters a and b. The function body is not provided yet.
2. Function Call
A function call is used to execute a function that has been declared and
defined. When a function is called, control is transferred to the function body,
and the function's code is executed.
Syntax:
function_name(argument_list);
• Function name: The name of the function to be executed.
• Argument list: The actual values passed to the function parameters
during the call.
Example:
int result = add(5, 3); // Function call
Here, add(5, 3) calls the add function with arguments 5 and 3. The result of the
function is assigned to the variable result.

3. Function Definition
A function definition provides the actual body (implementation) of the
function. It includes the code that gets executed when the function is called.
Syntax:
return_type function_name(parameter_list) {
// Function body
}
• Return type: Specifies the type of value the function will return.
• Function name: The name of the function.
• Parameter list: The list of parameters the function accepts.
• Function body: The block of code that defines what the function does.
It can include statements, expressions, and control flow structures.
Example:
int add(int a, int b) { // Function definition
return a + b; // Returns the sum of a and b
}
Here, the add function takes two integers as input, computes their sum, and
returns the result.

Example of all three together:


#include <iostream>
using namespace std;

// Function declaration
int add(int a, int b);

int main() {
// Function call
int result = add(10, 20);
cout << "Sum: " << result << endl;
return 0;
}

// Function definition
int add(int a, int b) {
return a + b;
}
Explanation:
1. Function Declaration: int add(int a, int b); informs the compiler that a
function named add exists.
2. Function Call: add(10, 20); calls the add function, passing 10 and 20 as
arguments.
3. Function Definition: int add(int a, int b) { return a + b; } is the actual
code that computes the sum of a and b.
In this example, the function add calculates the sum of two integers and
returns the result.

Pointers.
A pointer is a variable that holds the memory address of another variable.
Pointers are one of the most powerful features of C++ because they allow for
efficient manipulation of memory and the ability to work with dynamic data
structures like linked lists and trees.
1. Compile-Time Memory Location
Compile-time memory refers to the memory allocated by the compiler at the
time of program compilation. Variables that are declared statically or globally
are allocated memory at compile-time. This type of memory allocation is
determined before the program runs.
Example:
int x = 10; // 'x' is allocated memory at compile time
int *ptr = &x; // 'ptr' is a pointer to 'x', storing its memory address
Here, the memory address of x is determined at compile-time. The pointer ptr
holds the address of x. Since x is a normal variable (not dynamically
allocated), its memory is fixed during compilation and cannot change at
runtime.
Explanation:
• Compile-time memory is typically used for variables with a fixed size
known at compile time, like local variables or global variables.
• The pointer ptr stores the address of the variable x, which is allocated by
the compiler.
• No memory management operations (like new or delete) are required
for compile-time memory.

2. Run-Time Memory Location


Run-time memory refers to memory that is allocated during the execution
(runtime) of a program. This memory is dynamically allocated, meaning that it
is requested when the program runs and can be managed manually. In C++,
dynamic memory allocation is performed using the new keyword, and
deallocation is done using the delete keyword.
Example:
int *ptr = new int; // Dynamically allocate memory for an integer
*ptr = 20; // Assign value to the dynamically allocated memory

cout << "Value: " << *ptr << endl; // Output: 20

delete ptr; // Free the dynamically allocated memory


In this example:
• The new operator allocates memory at runtime for an integer.
• The pointer ptr holds the address of the memory allocated dynamically.
• The value 20 is stored at this memory location.
• Once the memory is no longer needed, the delete operator is used to
deallocate the memory.
Explanation:
• Run-time memory is used when the amount of memory required is not
known until the program runs.
• Pointers play a crucial role in managing dynamically allocated memory.
• Using pointers with dynamic memory requires careful memory
management to avoid memory leaks or dangling pointers.

Differences between Compile-Time and Run-Time Memory Allocation:


Aspect Compile-Time Memory Run-Time Memory
Done during program Done during program
Memory
compilation (before the execution (while the
Allocation
program runs). program runs).
No special keyword (e.g., new keyword is used for
Keyword Used normal variable dynamic memory
declarations). allocation.
Managed manually by the
Memory Managed automatically by
programmer (using
Management the compiler.
new/delete).
Fixed and known at compile Variable, can be decided
Memory Size
time. at runtime.
Usually in the stack (or
Memory
global data section for global Allocated on the heap.
Location
variables).
In summary:
• Compile-time memory location is used for variables with known size
during compilation, and pointers can store the addresses of these
variables.
• Run-time memory location involves dynamic memory allocation,
where pointers are essential to manage memory that is allocated during
program execution.

Classes and Objects in C++


1. Classes:
A class in C++ is a user-defined data type that acts as a blueprint for creating
objects. It encapsulates data and functions that operate on that data into a
single unit. Classes help organize code and promote reuse through
abstraction and encapsulation.
Key Characteristics of Classes:
• Encapsulation: Classes encapsulate data (attributes) and methods
(functions) that manipulate the data, providing a clear structure.
• Abstraction: Classes provide an abstraction layer, allowing
programmers to use complex functionalities without knowing the
implementation details.
• Reusability: Once a class is defined, it can be reused to create multiple
objects, reducing code redundancy.
Syntax:
class ClassName {
// Data members (attributes)
data_type member1;
data_type member2;
// Member functions (methods)
void functionName() {
// Function body
}
};
Example:
class Car {
public:
string brand; // Data member
int year; // Data member

void display() { // Member function


cout << "Brand: " << brand << ", Year: " << year << endl;
}
};

2. Objects:
An object is an instance of a class. When a class is defined, no memory is
allocated until an object of that class is created. Objects contain specific data
represented by the class's attributes and can use the functions defined in the
class.
Creating Objects: You can create an object using the class name followed by
the object name.
Example:
int main() {
Car myCar; // Creating an object of the Car class
myCar.brand = "Toyota"; // Assigning values to data members
myCar.year = 2020;

myCar.display(); // Calling the member function


return 0;
}
Explanation of the Example:
1. Class Definition: The Car class is defined with two data members
(brand and year) and a member function (display()).
2. Object Creation: In the main() function, an object myCar of the Car
class is created.
3. Accessing Members: The object's data members are accessed and
assigned values. The display() method is called to print the car's details.
Summary:
• Classes are blueprints that define attributes and behaviors for objects,
promoting encapsulation and abstraction.
• Objects are instances of classes that contain specific data and can
perform actions defined by the class methods.
Classes and objects are fundamental concepts in Object-Oriented
Programming (OOP), enabling better organization, code reuse, and
maintenance.
Infix to postfix
#include <iostream>
using namespace std;

class Convert {
char infix[30]; // Array to hold the infix expression
char postfix[30]; // Array to hold the postfix expression
char stk[30]; // Stack for operators
int top; // Stack pointer

public:
Convert() {
top = -1; // Initialize stack pointer
}

void read() {
cout << "Enter the infix expression: ";
cin >> infix; // Read the infix expression
}

void display() {
cout << "Infix Expression: " << infix << endl;
cout << "Postfix Expression: " << postfix << endl;
}
void infpost() {
int i = 0, j = 0; // Initialize indexes for infix and postfix
char symb;

while (infix[i] != '\0') {


symb = infix[i];

// If the symbol is an operand, add it to the postfix expression


if (symb >= 'a' && symb <= 'z') {
postfix[j++] = symb;
} else if (symb == '(') {
// Push '(' onto the stack
push(symb);
} else if (symb == ')') {
// Pop from stack until '(' is found
while (top != -1 && stk[top] != '(') {
postfix[j++] = pop();
}
pop(); // Remove '(' from the stack
} else {
// Handle operators
while (top != -1 && prio(stk[top]) >= prio(symb)) {
postfix[j++] = pop(); // Pop operators of higher or equal precedence
}
push(symb); // Push the current operator onto the stack
}
i++; // Move to the next symbol
}

// Pop all the operators from the stack


while (top != -1) {
postfix[j++] = pop();
}
postfix[j] = '\0'; // Null terminate the postfix string
}

int prio(char symb) {


// Return the precedence of operators
switch (symb) {
case '$': return 3;
case '*': return 2;
case '/': return 2;
case '+': return 1;
case '-': return 1;
case '(': return 0; // '(' has the lowest precedence
case ')': return -1; // ')' should not appear in the stack
default: return -1; // Handle unexpected characters
}
}

void push(char obj) {


top += 1;
stk[top] = obj; // Push the object onto the stack
}

char pop() {
char obj = stk[top];
top--; // Decrease stack pointer
return obj; // Return the popped object
}
};

int main() {
Convert C;
C.read(); // Read the infix expression
C.infpost(); // Convert infix to postfix
C.display(); // Display the results
return 0;

}
Postfix Evaluation
#include <iostream>
#define MAX 100
using namespace std;

class PostfEval {
private:
char postfix[MAX]; // Array to hold the postfix expression
int top; // Stack pointer
int stk[MAX]; // Stack for evaluation

public:
PostfEval() {
top = -1; // Initialize stack pointer
}

void push(int n) {
if (top + 1 == MAX) {
cout << "Stack is full\n";
return;
}
stk[++top] = n; // Push the value onto the stack
}
int pop() {
if (top != -1)
return stk[top--]; // Return the top value and decrement stack pointer
else {
cout << "Stack is empty\n";
return -1; // Indicate an error
}
}

void read() {
cout << "Enter a postfix expression (digits and operators): ";
cin >> postfix; // Read the postfix expression
}

int convert() {
int i = 0;
while (postfix[i] != '\0') {
// Check if the character is a digit
if (isdigit(postfix[i])) {
push(postfix[i] - '0'); // Convert char to int and push
} else {
// If the character is an operator, evaluate
int op2 = pop(); // Pop two operands from the stack
int op1 = pop(); // Pop the first operand
int result = evaloper(postfix[i], op1, op2); // Evaluate the operation
push(result); // Push the result back onto the stack
}
i++; // Move to the next character
}
return pop(); // Return the final result
}

int evaloper(char symb, int op1, int op2) {


switch (symb) {
case '+': return op1 + op2;
case '-': return op1 - op2;
case '*': return op1 * op2;
case '/':
if (op2 != 0)
return op1 / op2; // Avoid division by zero
else {
cout << "Error: Division by zero.\n";
return 0; // Return 0 or handle error appropriately
}
default:
cout << "Invalid operator: " << symb << endl;
return 0; // Handle unexpected characters
}
}
};

int main() {
PostfEval eval; // Create an instance of PostfEval
eval.read(); // Read the postfix expression
int val = eval.convert(); // Convert and evaluate the expression
cout << "The value after evaluation is: " << val << endl; // Display the result
return 0;
}

Decimal To Binary
#include <iostream>
#define MAX 100
using namespace std;

class Stack
{
public:
int top;
int stk[MAX];

Stack()
{
top = -1;
}
void push(int obj)
{
stk[++top] = obj;
}
int pop()
{
int obj;
return obj = stk[top--];
}
};

int main() {
Stack s;
int num,n,rem,binary=0;
cout<<"Enter The Number To Be Converted: ";
cin>>num;
n = num;
while(n != 0)
{
rem = n % 2;
s.push(rem);
n = n / 2;
}
while(s.top != -1)
{
binary = binary * 10 + s.pop();
}
cout<<"Binary Value of "<<num<<" is: "<<binary;
return 0;
}
Queues
1. Linear Queue
A linear queue is a data structure that follows the First In First Out (FIFO)
principle. In a linear queue, elements are added at the rear and removed from
the front.
Key Characteristics:
• Fixed size: The size of a linear queue is usually fixed.
• Waste of space: Once elements are dequeued, the space becomes
wasted, as it cannot be reused without moving all elements.
Operations:
• Enqueue: Add an element to the rear of the queue.
• Dequeue: Remove an element from the front of the queue.
Example Implementation:
#include <iostream>
#define MAX 5
using namespace std;

class Queue {
int front, rear;
int queue[MAX];
public:
Queue()
{
front = rear = -1;
}
void fnInsert()
{
int obj;
if (rear == MAX - 1)
{
cout << "Queue is full" << endl;
}
cout<<"Enter Element To Be Inserted: ";
cin>>obj;
if (front == -1)
front = 0; // First element
queue[++rear] = obj; // Add element
}

void fnDelete()
{
int obj;
if (front == -1 || front > rear)
{
cout << "Queue is empty" << endl;
}
obj = queue[front++];
cout<<"Deleted ELement Is: "<<obj<<endl;// Display action
}
void display()
{
if (front == -1)
{
cout << "Queue is empty" << endl;
}
cout << "Queue elements: ";
for (int i = front; i <= rear; i++) {
cout << queue[i] << " ";
}
cout << endl;
}
};

int main() {
Queue q;
char ch;
while(1)
{
cout<<"MENU\n";
cout<<"1.Insert\n";
cout<<"2.Delete\n";
cout<<"3.Display\n";
cout<<"4.Exit\n";
cout<<"Enter Your Choice: \n";
cin>>ch;
switch(ch)
{
case '1':q.fnInsert();
break;
case '2':q.fnDelete();
break;
case '3':q.display();
break;
case '4':exit(0);
break;
}
}
return 0;
}
2. Circular Queue
A circular queue is an extension of a linear queue where the last position is
connected back to the first position to form a circle. This eliminates the
problem of wasted space.
Key Characteristics:
• Efficient use of space: It reuses the space of dequeued elements.
• Requires two pointers: Front and rear pointers are used to manage the
positions.
Operations:
• Enqueue: Add an element to the rear.
• Dequeue: Remove an element from the front.
Example Implementation:
#include <iostream>
#define MAX 5
using namespace std;

class CircularQueue {
int front, rear, queue[MAX];
public:
CircularQueue() {
front = rear = -1;
}

void fnInsert() {
int obj;
if ((rear + 1) % MAX == front) {
cout << "Queue is full" << endl;
return;
}
cout << "Enter Element To Be Inserted: ";
cin >> obj;
if (front == -1)
front = 0; // Set front on first insertion
rear = (rear + 1) % MAX; // Circular increment
queue[rear] = obj; // Add element after rear has been updated
}
void fnDelete() {
if (front == -1) {
cout << "Queue is empty" << endl;
return;
}
int obj = queue[front];
if (front == rear) {
// If only one element was present
front = rear = -1;
} else {
front = (front + 1) % MAX; // Circular increment
}
cout << "Deleted Element Is: " << obj << endl;
}
void display() {
if (front == -1) {
cout << "Queue is empty" << endl;
return;
}
cout << "Queue elements: ";
if (front <= rear) {
// If the queue has not wrapped
for (int i = front; i <= rear; i++) {
cout << queue[i] << " ";
}
} else {
// If the queue has wrapped
for (int i = front; i < MAX; i++) {
cout << queue[i] << " ";
}
for (int i = 0; i <= rear; i++) {
cout << queue[i] << " ";
}
}
cout << endl;
}
};
int main() {
CircularQueue q;
char ch;
while (true) {
cout << "MENU\n";
cout << "1. Insert\n";
cout << "2. Delete\n";
cout << "3. Display\n";
cout << "4. Exit\n";
cout << "Enter Your Choice: ";
cin >> ch;
switch (ch) {
case '1': q.fnInsert(); break;
case '2': q.fnDelete(); break;
case '3': q.display(); break;
case '4': exit(0); break;
default: cout << "Invalid choice, please try again." << endl;
}
}
return 0;
}
3. Double-Ended Queue (Deque)
A double-ended queue (deque) is a data structure that allows insertion and
deletion of elements from both ends, i.e., the front and the rear.
Key Characteristics:
• Supports operations at both ends.
• Can be implemented using arrays or linked lists.
Operations:
• Enqueue Front: Add an element at the front.
• Enqueue Rear: Add an element at the rear.
• Dequeue Front: Remove an element from the front.
• Dequeue Rear: Remove an element from the rear.
Example Implementation:
• InputRestrictedDeque
#include <iostream>
#define MAX 5
using namespace std;

class InputRestrictedDeque {
int front, rear, queue[MAX];

public:
InputRestrictedDeque() {
front = rear = -1;
}
void fnInsert() {
if (rear == MAX - 1) {
cout << "Deque is full, cannot insert at rear" << endl;
return;
}
int obj;
cout << "Enter Element To Be Inserted at Rear: ";
cin >> obj;

if (front == -1)
front = 0; // Set front on first insertion
queue[++rear] = obj; // Insert at rear
}

void fnDeleteFront() {
if (front == -1) {
cout << "Deque is empty" << endl;
return;
}
int obj = queue[front];
if (front == rear) {
// If only one element was present
front = rear = -1;
} else {
front++; // Move front forward
}
cout << "Deleted Element from Front Is: " << obj << endl;
}

void fnDeleteRear() {
if (front == -1) {
cout << "Deque is empty" << endl;
return;
}
int obj = queue[rear];
if (front == rear) {
// If only one element was present
front = rear = -1;
} else {
rear--; // Move rear backward
}
cout << "Deleted Element from Rear Is: " << obj << endl;
}

void display() {
if (front == -1) {
cout << "Deque is empty" << endl;
return;
}
cout << "Deque elements: ";
for (int i = front; i <= rear; i++) {
cout << queue[i] << " ";
}
cout << endl;
}
};

int main() {
InputRestrictedDeque dq;
char ch;
while (true) {
cout << "MENU\n";
cout << "1. Insert at Rear\n";
cout << "2. Delete from Front\n";
cout << "3. Delete from Rear\n";
cout << "4. Display\n";
cout << "5. Exit\n";
cout << "Enter Your Choice: ";
cin >> ch;
switch (ch) {
case '1': dq.fnInsert(); break;
case '2': dq.fnDeleteFront(); break;
case '3': dq.fnDeleteRear(); break;
case '4': dq.display(); break;
case '5': exit(0); break;
default: cout << "Invalid choice, please try again." << endl;
}
}
return 0;
}

• OutputRestrictedDeque
#include <iostream>
#define MAX 5
using namespace std;

class OutputRestrictedDeque {
int front, rear, queue[MAX];

public:
OutputRestrictedDeque() {
front = rear = -1;
}

void fnInsertFront() {
if (front == 0) {
cout << "Deque is full, cannot insert at front" << endl;
return;
}
int obj;
cout << "Enter Element To Be Inserted at Front: ";
cin >> obj;

if (front == -1)
front = 0; // Set front on first insertion
else
front--; // Move front backward

queue[front] = obj; // Insert at front


}

void fnInsertRear() {
if (rear == MAX - 1) {
cout << "Deque is full, cannot insert at rear" << endl;
return;
}
int obj;
cout << "Enter Element To Be Inserted at Rear: ";
cin >> obj;

if (rear == -1)
rear = 0; // Set rear on first insertion
else
rear++; // Move rear forward

queue[rear] = obj; // Insert at rear


}

void fnDelete() {
if (front == -1) {
cout << "Deque is empty" << endl;
return;
}
int obj = queue[front];
if (front == rear) {
// If only one element was present
front = rear = -1;
} else {
front++; // Move front forward
}
cout << "Deleted Element from Front Is: " << obj << endl;
}

void display() {
if (front == -1) {
cout << "Deque is empty" << endl;
return;
}
cout << "Deque elements: ";
for (int i = front; i <= rear; i++) {
cout << queue[i] << " ";
}
cout << endl;
}
};

int main() {
OutputRestrictedDeque dq;
char ch;
while (true) {
cout << "MENU\n";
cout << "1. Insert at Front\n";
cout << "2. Insert at Rear\n";
cout << "3. Delete from Front\n";
cout << "4. Display\n";
cout << "5. Exit\n";
cout << "Enter Your Choice: ";
cin >> ch;
switch (ch) {
case '1': dq.fnInsertFront(); break;
case '2': dq.fnInsertRear(); break;
case '3': dq.fnDelete(); break;
case '4': dq.display(); break;
case '5': exit(0); break;
default: cout << "Invalid choice, please try again." << endl;
}
}
return 0;
}

4. Priority Queue
A priority queue is an abstract data type where each element has a priority
assigned to it. Elements with higher priority are dequeued before elements
with lower priority.
Key Characteristics:
• Can be implemented using arrays, linked lists, or heaps.
• Not strictly FIFO: The order of dequeuing depends on priority.
Operations:
• Enqueue: Add an element with a priority.
• Dequeue: Remove and return the element with the highest priority.
Example Implementation:
#include <iostream>
#define MAX 5
using namespace std;

class PriorityQueue {
int front, rear;
int queue[MAX];

public:
PriorityQueue() {
front = rear = -1;
}

void fnInsert() {
if (rear == MAX - 1) {
cout << "Priority Queue is full" << endl;
return;
}

int obj;
cout << "Enter Element To Be Inserted: ";
cin >> obj;
if (front == -1)
front = 0; // Set front on first insertion

rear++; // Move rear forward


queue[rear] = obj; // Insert element
}

void fnDelete() {
if (front == -1) {
cout << "Priority Queue is empty" << endl;
return;
}

// Find the index of the element with the minimum value


int minIndex = front;
for (int i = front + 1; i <= rear; i++) {
if (queue[i] < queue[minIndex]) {
minIndex = i; // Update minIndex if a lower value is found
}
}

// Display and remove the element with the minimum value


cout << "Deleted Element Is: " << queue[minIndex] << endl;
// Shift elements to remove the minIndex element
for (int i = minIndex; i < rear; i++) {
queue[i] = queue[i + 1];
}
rear--; // Decrease rear

// Reset front if the queue is empty


if (rear == -1)
front = -1;
}

void display() {
if (front == -1) {
cout << "Priority Queue is empty" << endl;
return;
}
cout << "Priority Queue elements:" << endl;
for (int i = front; i <= rear; i++) {
cout << "Element: " << queue[i] << endl;
}
}
};
int main() {
PriorityQueue pq;
char ch;
while (true) {
cout << "MENU\n";
cout << "1. Insert\n";
cout << "2. Delete (min value)\n";
cout << "3. Display\n";
cout << "4. Exit\n";
cout << "Enter Your Choice: ";
cin >> ch;
switch (ch) {
case '1': pq.fnInsert(); break;
case '2': pq.fnDelete(); break;
case '3': pq.display(); break;
case '4': exit(0); break;
default: cout << "Invalid choice, please try again." << endl;
}
}
return 0;
}

Summary:
• Linear Queue: Basic FIFO structure; elements added at the rear and
removed from the front.
• Circular Queue: A circular version of a linear queue, allowing efficient
space usage.
• Double-Ended Queue (Deque): Allows insertion and deletion at both
ends.
• Priority Queue: Elements are dequeued based on priority, not strictly
FIFO.
These data structures are fundamental in computer science and have various
applications in algorithms and systems.

You might also like