C++ R
C++ R
RECORD
SUBMITTED BY
NAME :
REG NO :
SIGNATURE SIGNATURE
LAB IN-CHARGE HEAD OF DEPARTMENT
FLOWCHART:
start
stop
9
Aim :
To write a C++ program to illustrate the use of Constructors and Destructors
Software Required:
VSCODE (C++ compiler)
Theory:
In C++, constructors and destructors are special member functions of a class. A
constructor is automatically called when an object is created and is used to initialize data
members. It has the same name as the class and no return type. Constructors can be default,
parameterized, or copy constructors. A destructor is automatically called when an object is
destroyed and is used to release resources. It has the same name as the class, preceded by a
tilde ~, and it also has no return type or parameters. These features help manage object lifecycle
efficiently.
Coding:
#include <iostream>
#include <string>
using namespace std
class Car {
private:
string brand;
int year;
public:
// Default constructor
Car() {
brand = "xxx";
year = 0;
cout << "Default constructor" << endl;
}
// Parameterized constructor
Car(string b, int y) {
cout << "Parameterized constructor" << endl;
10
Output:
Default constructor
Parameterized constructor
Copy constructor
Brand: xxx, Year: 0
Brand: Toyota, Year: 2020
Brand: Toyota, Year: 2020
Destructor called
Destructor called
Destructor called
11
brand = b;
year = y;
}
Car(const Car &c) {
brand = c.brand;
year = c.year;
cout << "Copy constructor" << endl;
}
// Destructor
~Car() {
cout << "Destructor called" << endl;
}
// Display function
void display() {
cout << "Brand: " << brand << ", Year: " << year << endl;
}
};
int main() {
Car c1; // Default constructor
Car c2("Toyota", 2020); // Parameterized constructor
Car c3 = c2; // Copy constructor
c1.display();
c2.display();
c3.display();
return 0;
}
Result:
Hence,the above program has been executed and verified successfully.
12
FLOWCHART:
start
Create a object b1
Read values of b1
stop
13
Aim:
To write a C++ program that demonstrates the use of classes, member functions, and friend
functions
Software Required:
VSCODE (C++ compiler)
Theory:
A class is a user-defined data type that groups variables and functions together.
Member functions are functions defined inside a class that operate on its objects and can
access private data. A friend function is a non-member function that is given special
permission to access the private and protected members of a class. It is declared using the friend
keyword inside the class.
Coding:
#include <iostream>
using namespace std;
class Box {
private:
int length;
public:
void setLength(int l) {
length = l;
}
void displayLength() {
cout << "Length = " << length << endl;
}
friend void doubleLength(Box b);
};
void doubleLength(Box b) {
cout << "Doubling the length" << endl;
cout << "Double Length = " << b.length * 2 << endl;
14
Output:
Length = 15
Doubling the length
Double Length = 30
15
}
int main() {
Box b1;
b1.setLength(15);
b1.displayLength();
doubleLength(b1);
return 0;
}
Result:
Hence,the above program has been executed and verified successfully.
16
FLOWCHART:
a)
start
Input n values
Double and
Print
print
values
length value
stop
17
Aim :
a)To write a C++ program to dynamically allocate memory space using new operator
b) To write a C++ program to implement function overloading.
b)To write a C++ program to overload the addition(+) operator.
Software required :
VSCODE (C++ compiler)
Theory:
Dynamic memory allocation allows memory to be allocated during runtime using new
and released using delete, which helps manage memory efficiently when the size of data is not
known in advance. Function overloading enables multiple functions with the same name but
different parameters, improving code readability and flexibility. Operator overloading allows
built-in operators (like +, -, etc.) to be redefined for user-defined types such as classes, making
objects behave more like primitive types. Together, these features enhance program versatility,
reusability, and efficiency.
Coding:
a)
#include <iostream>
using namespace std;
int main() {
int size;
cout << "Enter the size of the array: ";
cin >> size;
int* arr = new int[size];
cout << "Enter " << size << " elements:\n";
for (int i = 0; i < size; i++) {
cin >> arr[i];
}
cout << "You entered: ";
18
Output:
10 10 10 10 10
Enter 5 values:
12332
12332
FLOWCHART:
b)
start
stop
19
delete[] arr;
return 0;
}
b)
#include<iostream>
using namespace std;
int Area(int,int);
int Area(double,double);
double Area(double);
int main(){
int area;
double cir, a2;
area= Area(3,5);
cir=Area(2);
a2=Area(3.4,5.2);
cout<<"Area ="<<area;
cout<<"\nArea = "<<a2;
cout<<"\nArea of circle = "<<cir;
return 0;
}
int Area(int a, int b){
return a*b;
}
int Area(double a, double b){
return a*b;
20
Output:
Area =15
Area = 17
Area of circle = 12.56
FLOWCHART:
c)
start
Print values
stop
21
}
double Area(double a){
double c;
c=3.14*a*a;
return c;
}
c)
#include <iostream>
using namespace std;
class comp{
int real,img;
public:
comp(int r=0, int i=0){
real =r;
img=i;
}
comp operator+(comp &c2){
comp a;
a.real= real+ c2.real;
a.img = img +c2.img;
return a;
}
void print(){
cout<<real<<" +i"<<img <<endl;
}
};
int main(){
comp c1(1,2), c2(3,4), c3;
c3= c1+c2;
c3.print();
22
Output:
4 +i6
23
return 0;
}
Result :
Hence,the above programs have been executed and verified successfully.
24
FLOWCHART:
a)
start
stop
25
Aim :
a)To write a C++ program to illustrate single inheritance
b)To write a C++ program to illustrate multiple inheritance
c)To write a C++ program to illustrate multilevel inheritance
d)To write a C++ program to illustrate hierarchical inheritance
e)To write a C++ program to illustrate hybrid inheritance
Software Required:
VSCODE (C++ compiler)
Theory:
Inheritance is an object-oriented programming feature that allows a class (called the
derived or child class) to inherit properties and behaviors from another class (called the base
or parent class). The main types of inheritance include single inheritance, where one class
inherits from one base class; multiple inheritance, where a class inherits from two or more
base classes; multilevel inheritance, where a class is derived from another derived class;
hierarchical inheritance, where multiple classes inherit from a single base class; and hybrid
inheritance, which is a combination of two or more types. Inheritance promotes code
reusability, modularity, and helps organize complex systems into simpler class structures.
Coding:
a)
#include <iostream>
using namespace std;
class Sports {
protected:
int players;
string mode;
int duration;
};
Output:
No. of players: 11
Mode: outdoor
Duration (mins): 90
Bootmodel: Adidas
League: laliga
27
string bootmodel;
string league;
public:
football(int players, int b, string c, string boot, string l) {
this->players = players;
mode = c;
duration = b;
bootmodel = boot;
league = l;
}
void disp() {
cout << "No. of players: " << players << endl;
cout << "Mode: " << mode << endl;
cout << "Duration (mins): " << duration << endl;
cout << "Bootmodel: " << bootmodel << endl;
cout << "League: " << league << endl;
}
};
int main() {
football F1(11, 90, "outdoor", "Adidas", "laliga");
F1.disp();
return 0;
}
b)
#include <iostream>
using namespace std;
28
FLOWCHART:
b)
start
Print ingredients
stop
29
class India {
protected:
string species;
};
class China {
public:
string rice;
int kg;
string oil;
float ltr;
};
void disp() {
cout << "Spice: " << species << endl;
cout << "Kg: " << kg << endl;
cout << "Rice Type: " << rice << endl;
30
Output:
Spice: Pepper
Kg: 2
Rice Type: Sticky rice
Oil: flax
Litres of oil: 0.5
Plate type: China
FLOWCHART:
c)
start
stop
31
int main() {
curryrice c1("Pepper", 2, "Sticky rice", "flax", 0.5, "China");
c1.disp();
return 0;
}
c)
#include <iostream>
using namespace std;
class Movie {
protected:
int year;
int duration;
};
Output:
Movie name: Leo
Year of release: 2023
Duration (mins): 185
No. of songs: 2
Actor: Vijay
Actress: Trisha
33
public:
Leo(int a, string c, int b, int s, string h, string h0) {
year = a;
name = c;
duration = b;
songs = s;
hero = h;
heroine = h0;
}
void disp() {
cout << "Movie name: " << name << endl;
cout << "Year of release: " << year << endl;
cout << "Duration (mins): " << duration << endl;
cout << "No. of songs: " << songs << endl;
cout << "Actor: " << hero << endl;
cout << "Actress: " << heroine << endl;
}
};
int main() {
Leo l(2023, "Leo", 185, 2, "Vijay", "Trisha");
l.disp();
return 0;
}
d)
#include <iostream>
using namespace std;
class Vehicle {
34
FLOWCHART:
d)
start
stop
35
protected:
string price;
string brand;
};
public:
Car(string a, int h, string brd, string te) {
price = a;
hp = h;
brand = brd;
tire = te;
}
void disp() {
cout << "Price: ₹" << price << endl;
cout << "Brand name: " << brand << endl;
cout << "Tire model: " << tire << endl;
cout << "Horsepower: " << hp << " HP" << endl;
}
};
Output:
Price: ₹10,00,000
Brand name: BMW
Tire model: Goodyear
Horsepower: 300 HP
Price: ₹1,30,000
Brand name: OLA
Charging Time: 6 hrs
Range: 190 Km
37
public:
eBike(string a, int h, string brd, int ce) {
price = a;
range = h;
brand = brd;
charge = ce;
}
void disp() {
cout << "Price: ₹" << price << endl;
cout << "Brand name: " << brand << endl;
cout << "Charging Time: " << charge << " hrs" << endl;
cout << "Range: " << range << " Km" << endl;
}
};
int main() {
Car c1("10,00,000", 300, "BMW", "Goodyear");
eBike b1("1,30,000", 190, "OLA", 6);
c1.disp();
cout<<endl;
b1.disp();
return 0;
}
e)
#include <iostream>
using namespace std;
class Person {
38
FLOWCHART:
e)
start
stop
39
protected:
string name;
int id;
public:
void setPerson(string n, int i) {
name = n;
id = i;
}
void displayPerson() {
cout << "Name: " << name << endl;
cout << "ID: " << id << endl;
}
};
class Academics : virtual public Person {
protected:
float academicMarks;
public:
void setAcademicMarks(float m) {
academicMarks = m;
}
void displayAcademics() {
cout << "Academic Marks: " << academicMarks << "%" << endl;
}
};
class Sports: virtual public Person {
protected:
float sportsScore;
public:
void setSportsScore(float s) {
40
Output:
----- Student Result -----
Name: Alice
ID: 101
Academic Marks: 85.5%
Sports Score: 92%
Overall Performance: 88.75%
41
sportsScore = s;
}
void displaySports() {
cout << "Sports Score: " << sportsScore << "%" << endl;
}
};
class Result : public Academics, public Sports {
public:
void displayResult() {
cout << "----- Student Result -----" << endl;
displayPerson();
displayAcademics();
displaySports();
float total = (academicMarks + sportsScore) / 2;
cout << "Overall Performance: " << total << "%" << endl;
}
};
int main() {
Result student;
student.setPerson("Alice", 101);
student.setAcademicMarks(85.5);
student.setSportsScore(92.0);
student.displayResult();
return 0;
}
Result :
Hence,the above programs have been executed and verified successfully
42
FLOWCHART:
start
stop
43
Aim :
To write a C++ program to demonstrate the use of virtual functions and dynamic binding.
Software Required :
VSCODE (C++ compiler)
Theory:
Virtual functions enable runtime polymorphism by allowing a base class pointer to
call functions in derived classes dynamically at runtime. When a function is declared as virtual
in the base class and overridden in the derived class, the decision of which function to execute
is made during program execution — a process known as dynamic binding or late binding.
This ensures that the correct version of the function is called based on the actual object type,
not the pointer type. Virtual functions are essential in implementing flexible and extensible
programs using inheritance and polymorphism.
Coding:
#include <iostream>
using namespace std;
class Base {
public:
virtual void car() {
cout << "Bought a car" << endl;
}
virtual ~Base() {
cout << "Sold a car" << endl;
}
};
class Bmw : public Base {
public:
void car() override {
cout << "Buy a BMW" << endl;
44
Output:
Buy a BMW
Sell the BMW
Sold a car
45
}
~Bmw() {
cout << "Sell the BMW" << endl;
}
};
int main() {
Base* c1;
Bmw obj;
c1 = &obj;
c1->car();
return 0;
}
Result :
Hence,the above programs have been executed and verified successfully.
46
Algorithm:
1. Start
2. Create an array and input the number of elements (n)
3. Input n elements into the array
4. Repeat until user selects Exit:
a. Show menu with choices: Display, Insert, Delete, Search, Update, Exit
b. Get user's choice
c. If Display, print all elements in the array
d. If Insert, input position and value, shift elements, insert value, increase n
e. If Delete, input position, shift elements left, decrease n
f. If Search, input value, check each element, print position if found
g. If Update, input position and new value, update that element
5. Print “Exiting...” and stop
47
Aim :
To write a C++ program that implements various operations on arrays such as
insertion, deletion, traversal, searching, and updating using a menu-driven approach.
Software Required :
VSCODE (C++ compiler)
Theory:
Arrays are used to store multiple values of the same data type in contiguous memory
locations, allowing efficient access and manipulation of elements. Various operations can be
performed on arrays, such as insertion, deletion, traversal, searching, and updating. Insertion
involves adding a new element at a specific position, which requires shifting subsequent
elements to the right. Deletion removes an element from a specific index by shifting the
remaining elements to the left. Traversal is the process of accessing each element, typically
using loops. Searching can be done through linear or binary methods, depending on whether
the array is sorted, while updating allows modification of a value at a particular index.
Coding:
#include <iostream>
using namespace std;
return;
}
if (pos < 0 || pos > n) {
cout << "Invalid position!\n";
return;
}
for (int i = n; i > pos; i--)
arr[i] = arr[i - 1];
arr[pos] = val;
n++;
cout << "Element inserted.\n";
}
}
cout << "Element not found.\n";
}
int main() {
int arr[SIZE], n = 0, choice, val, pos;
do {
cout << "\nMenu:\n";
cout << "1. Display\n2. Insert\n3. Delete\n4. Search\n5. Update\n6. Exit\n";
cout << "Enter your choice: ";
cin >> choice;
switch (choice) {
case 1:
52
Output:
Enter number of elements: 5
Enter elements:
10 20 30 40 50
Menu:
1. Display
2. Insert
3. Delete
4. Search
5. Update
6. Exit
Enter your choice: 1
Array elements: 10 20 30 40 50
display(arr, n);
break;
case 2:
cout << "Enter position and value to insert: ";
cin >> pos >> val;
insert(arr, n, pos, val);
break;
case 3:
cout << "Enter position to delete: ";
cin >> pos;
deleteElement(arr, n, pos);
break;
case 4:
cout << "Enter value to search: ";
cin >> val;
search(arr, n, val);
break;
case 5:
cout << "Enter position and new value to update: ";
cin >> pos >> val;
update(arr, n, pos, val);
break;
case 6:
cout << "Exiting...\n";
break;
default:
cout << "Invalid choice!\n";
}
} while (choice != 6);
54
return 0;
}
Result:
Hence,the above programs have been executed and verified successfully.
56
Algorithm:
1. Start and initialize an empty stack with top set to -1.
2. For each push operation, check if the stack is full; if not, increment top, insert the
value, and display a message.
3. Push values 10, 20, and 30 using the push operation.
4. To display the stack, check if it's empty; if not, print elements from top to bottom.
5. Show current stack elements using the display function.
6. To peek, check if the stack is empty; if not, print the top element.
7. Use peek to display the current top element.
8. For each pop, check if the stack is empty; if not, print the top element and
decrement top.
9. Pop one element and display the stack.
10. Pop two more elements to empty the stack.
11. Attempt another pop and display "Stack Underflow" since the stack is empty.
12. End the program.
57
Aim :
To write a C++ program to implement various operations on Stacks such as push, pop
and peek operations using Arrays.
Software Required:
VSCODE(C++ compiler)
Theory:
A stack is a linear data structure that works on the Last In First Out (LIFO) principle. It
can be implemented using arrays in C++ with a variable top to track the top element. Basic
operations include push (to insert), pop (to remove), peek (to view the top), and display (to
print all elements). Stack overflow occurs when inserting into a full stack, and underflow
occurs when removing from an empty stack. This implementation is simple and efficient when
the stack size is fixed.
Coding:
#include <iostream>
using namespace std;
#define SIZE 100
class Stack {
int arr[SIZE];
int top;
public:
Stack() {
top = -1;
}
void push(int value) {
if (top >= SIZE - 1) {
cout << "Stack Overflow!" << endl;
} else {
top++;
58
59
arr[top] = value;
cout << value << " pushed to stack." << endl;
}
}
void pop() {
if (top < 0) {
cout << "Stack Underflow!" << endl;
} else {
cout << "Popped element: " << arr[top] << endl;
top--;
}
}
void peek() {
if (top < 0) {
cout << "Stack is empty!" << endl;
} else {
cout << "Top element: " << arr[top] << endl;
}
}
void display() {
if (top < 0) {
cout << "Stack is empty!" << endl;
} else {
cout << "Stack elements (top to bottom): ";
for (int i = top; i >= 0; i--)
cout << arr[i] << " ";
cout << endl;
}
}
};
60
Output:
10 pushed to stack.
20 pushed to stack.
30 pushed to stack.
Stack elements (top to bottom): 30 20 10
Top element: 30
Popped element: 30
Stack elements (top to bottom): 20 10
Popped element: 20
Popped element: 10
Stack Underflow!
61
int main() {
Stack s;
s.push(10);
s.push(20);
s.push(30);
s.display();
s.peek();
s.pop();
s.display();
s.pop();
s.pop();
s.pop();
return 0;
}
Result :
Hence,the above programs have been executed and verified successfully
62
Algorithm:
1. Start the program and initialize front and rear to -1.
2. Enqueue 10, 20, and 30 by checking for overflow, setting front if needed,
incrementing rear, and inserting each value.
3. Display the queue if not empty by printing elements from front to rear.
4. Peek by checking if the queue is empty and printing the front element.
5. Dequeue once by checking for underflow, printing the front element, and
incrementing front.
6. Display the queue to show remaining elements.
7. Dequeue twice more to empty the queue, printing each element.
8. Attempt one more dequeue, detect underflow, and display an error message.
9. End the program.
63
Aim :
To write a C++ program to implement various operations on Queues such as enqueue,
dequeue, peek and display operations using Arrays.
Software Required:
VSCODE (C++ compiler)
Theory:
A queue is a linear data structure that works on the First In First Out (FIFO) principle.
It can be implemented using arrays in C++ with two variables, front and rear, to track the
positions of elements. Basic operations include enqueue (to insert at the rear), dequeue (to
remove from the front), peek (to view the front element), and display (to print all elements).
Queue overflow occurs when inserting into a full queue, and underflow occurs when removing
from an empty queue. This implementation is simple and efficient when the queue size is fixed.
Coding:
#include <iostream>
using namespace std;
#define SIZE 100
class Queue {
int arr[SIZE];
int front, rear;
public:
Queue() {
front = -1;
rear = -1;
}
Output:
10 enqueued to queue.
20 enqueued to queue.
30 enqueued to queue.
Queue elements (front to rear): 10 20 30
Front element: 10
Dequeued element: 10
Queue elements (front to rear): 20 30
Dequeued element: 20
Dequeued element: 30
Queue Underflow!
65
void dequeue() {
if (front == -1 || front > rear) {
cout << "Queue Underflow!" << endl;
} else {
cout << "Dequeued element: " << arr[front] << endl;
front++;
}
}
void peek() {
if (front == -1 || front > rear) {
cout << "Queue is empty!" << endl;
} else {
cout << "Front element: " << arr[front] << endl;
}
}
void display() {
if (front == -1 || front > rear) {
cout << "Queue is empty!" << endl;
} else {
66
67
int main() {
Queue q;
q.enqueue(10);
q.enqueue(20);
q.enqueue(30);
q.display();
q.peek();
q.dequeue();
q.display();
q.dequeue();
q.dequeue();
q.dequeue();
return 0;
}
Result :
Hence,the above programs have been executed and verified successfully.
68
Algorithm:
1. Start the program and take an infix expression as input from the user.
2. Convert infix to postfix:
a. Scan each character:
– If it's a digit, append it to the result.
– If it's '(', push to stack.
– If it's ')', pop and append from stack until '(' is found.
– If it's an operator, pop operators of higher or equal precedence and then push
current operator.
b. After scanning, pop all remaining operators to result.
3. Convert infix to prefix:
a. Reverse the infix string.
b. Swap '(' with ')' and vice versa.
c. Apply the same infix-to-postfix logic.
d. Reverse the result to get prefix.
4. Evaluate postfix expression:
a. Scan from left to right.
b. Push operands to stack.
c. On encountering an operator, pop two values, apply the operation, and push
result.
5. Evaluate prefix expression:
a. Scan from right to left.
b. Push operands to stack.
c. On encountering an operator, pop two values, apply the operation, and push
result.
6. Display postfix and prefix expressions and their evaluations.
7. End the program.
69
Aim :
To write a C++ program to evaluate the infix expressions by converting into Prefix
and Postfix expressions.
Software Required:
VSCODE (C++ compiler)
Theory:
Infix expressions are commonly used in mathematics, where operators appear between
operands (e.g., A + B). However, they are not efficient for computers to evaluate directly due
to the need to handle operator precedence and parentheses. To simplify evaluation, infix
expressions are first converted into postfix (Reverse Polish Notation) or prefix (Polish
Notation) form.
In postfix expressions, operators follow their operands (e.g., AB+). Conversion involves
scanning the infix expression left to right, using a stack to manage operators and precedence
rules. Similarly, prefix expressions place operators before operands (e.g., +AB). Prefix
conversion is done by reversing the infix expression, swapping brackets, converting to postfix,
and then reversing the result.
Once converted, both postfix and prefix expressions are easy to evaluate using a stack. For
postfix, scan from left to right; for prefix, scan from right to left. Operands are pushed onto the
stack, and on encountering an operator, the required number of operands are popped, the
operation is performed, and the result is pushed back. The final value in the stack is the result
of the expression.
Coding:
#include <iostream>
#include <stack>
#include <algorithm>
#include <cctype>
using namespace std;
int precedence(char op) {
if(op == '+'||op == '-') return 1;
if(op == '*'||op == '/') return 2;
return 0;
70
71
}
int applyOp(int a, int b, char op) {
switch(op) {
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/': return a / b;
}
return 0;
}
string infixToPostfix(string s) {
stack<char> st;
string result;
for(char ch : s) {
72
73
if(isdigit(ch))
result += ch;
else if(ch == '(')
st.push(ch);
else if(ch == ')') {
while(!st.empty() && st.top() != '(') {
result += st.top();
st.pop();
}
st.pop();
} else {
while(!st.empty() && precedence(st.top()) >= precedence(ch)) {
result += st.top();
st.pop();
}
st.push(ch);
}
}
while(!st.empty()) {
result += st.top();
st.pop();
}
return result;
}
string infixToPrefix(string s) {
reverse(s.begin(), s.end());
}
string postfix = infixToPostfix(s);
reverse(postfix.begin(), postfix.end());
return postfix;
}
int evaluatePostfix(string expr) {
stack<int> st;
for(char ch : expr) {
if(isdigit(ch))
st.push(ch - '0');
else {
int b = st.top(); st.pop();
int a = st.top(); st.pop();
st.push(applyOp(a, b, ch));
}
}
return st.top();
}
int evaluatePrefix(string expr) {
stack<int> st;
for(int i = expr.length() - 1; i >= 0; i--) {
char ch = expr[i];
if(isdigit(ch))
st.push(ch - '0');
else {
int a = st.top(); st.pop();
int b = st.top(); st.pop();
st.push(applyOp(a, b, ch));
}
}
76
Output:
Enter infix expression : 6+2*3-4
Postfix: 623*+4-
Prefix: -+6*234
Postfix Evaluation: 8
Prefix Evaluation: 8
77
return st.top();
}
int main() {
string infix;
cout << "Enter infix expression : ";
cin >> infix;
return 0;
}
Result :
Hence,the above programs have been executed and verified successfully.
78
Algorithm:
1. Start the program and define a Node class with data and next pointer.
2. Define a LinkedList class with head initialized to NULL.
3. To insert at end, create a new node and link it after the last node.
4. To insert at front, create a new node and point it to current head, then update head.
5. To delete a node, search for the value, unlink it, and free memory.
6. To display, traverse from head and print each node until NULL.
7. To search, traverse the list and compare each node’s data.
8. In main(), perform operations like insertions, deletion, display, and search.
9. End the program.
79
Aim :
To write a C++ program to implement various Operations on Linked lists such as
insertion, deletion, traversal and search.
Software Required:
VSCODE(C++ compiler)
Theory:
A linked list is a dynamic data structure where each node contains data and a pointer to
the next node. This program implements a singly linked list in C++ with basic operations:
inserting at the front and end, deleting a node by value, searching for a value, and displaying
the list. It uses a Node class for individual elements and a LinkedList class to manage
operations using the head pointer. Unlike arrays, linked lists allow efficient insertion and
deletion without shifting elements.
Coding:
#include <iostream>
using namespace std;
class Node {
public:
int data;
Node* next;
Node(int value) {
data = value;
next = nullptr;
}
};
class LinkedList {
private:
Node* head;
80
81
public:
LinkedList() {
head = nullptr;
}
void insertEnd(int value) {
Node* newNode = new Node(value);
if (!head) {
head = newNode;
} else {
Node* temp = head;
while (temp->next)
temp = temp->next;
temp->next = newNode;
}
cout << value << " inserted at end.\n";
}
void insertFront(int value) {
Node* newNode = new Node(value);
newNode->next = head;
head = newNode;
cout << value << " inserted at front.\n";
}
void deleteNode(int value) {
if (!head) {
cout << "List is empty.\n";
return;
}
if (head->data == value) {
Node* toDelete = head;
head =
82
83
delete toDelete;
cout << value << " deleted from list.\n";
return;
}
Node* temp = head;
while (temp->next && temp->next->data != value)
temp = temp->next;
if (temp->next) {
Node* toDelete = temp->next;
temp->next = temp->next->next;
delete toDelete;
cout << value << " deleted from list.\n";
} else {
cout << value << " not found in list.\n";
}
}
void display() {
if (!head) {
cout << "List is empty.\n";
return;
}
Node* temp = head;
cout << "Linked List: ";
while (temp) {
cout << temp->data << " -> ";
temp = temp->next;
}
cout << "NULL\n";
}
84
Output:
10 inserted at end.
20 inserted at end.
5 inserted at front.
Linked List: 5 -> 10 -> 20 -> NULL
20 found in list.
10 deleted from list.
Linked List: 5 -> 20 -> NULL
10 not found in list.
85
Result :
Hence,the above programs have been executed and verified successfully.
86
Algorithm:
a)
1. Define a Node structure with data, left, and right pointers.
2. Implement addnode(data) to create and return a new node.
3. Write recursive functions:
o preorder() → Root, Left, Right
o inorder() → Left, Root, Right
o postorder() → Left, Right, Root
4. In main(), create the root node using addnode(1).
5. Add child nodes to build the binary tree structure.
6. Call and print results of preorder(), inorder(), and postorder() on the root.
7. End the program.
b)
1. Define a graph class with vertex count and adjacency list.
2. In addEdge(u, v), connect both u → v and v → u.
3. In BFS(start), use a queue to visit nodes level by level.
4. In DFS(start), use recursion to visit nodes depth-wise.
5. In main(), create a graph with 6 nodes.
6. Add edges: (0-1), (0-2), (1-3), (2-4), (3-5), (4-5).
7. Call BFS(0) and print nodes in BFS order.
8. Call DFS(0) and print nodes in DFS order.
9. End.
87
Aim :
To write a C++ program to implement the following:
a) Binary Tree Traversal
b) Graph Traversal(
Software Required:
VSCODE(C++ compiler)
Theory:
In preorder traversal, the root node is visited first, followed by the left subtree, and
then the right subtree. It is commonly used to copy trees or evaluate prefix expressions.
In inorder traversal, the left subtree is visited first, then the root, and finally the right
subtree. This traversal is especially useful in binary search trees as it gives nodes in sorted
order.
In postorder traversal, the left and right subtrees are visited before the root. It is often
used for deleting trees or evaluating postfix expressions.
Breadth-First Search (BFS) explores nodes level by level using a queue. It starts at a
given node and visits all its neighbours before going deeper. BFS is useful for finding the
shortest path in an unweighted graph.
Depth-First Search (DFS) explores as far as possible along one path before
backtracking. It uses recursion or a stack. DFS is helpful for checking connectivity, solving
puzzles, and detecting cycles in graphs.
Coding:
a)
#include<iostream>
using namespace std;
struct Node {
int data;
Node* left;
Node* right;
};
Node* addnode(int data) {
88
Output:
a)
Preorder
1
2
23
6
3
4
Inorder
23
2
6
1
4
3
Postorder
23
6
2
4
3
1
89
Output:
b)
Breadth First Search:
012345
Depth First Search:
013542
95
int main(){
graph g(6);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 3);
g.addEdge(2, 4);
g.addEdge(3, 5);
g.addEdge(4, 5);
g.BFS(0);
g.DFS(0);
}
Result :
Hence,the above programs have been executed and verified successfully.
96
Algorithm:
a)
1. Define a graph as an adjacency list with edge weights using vector<pair<int,int>>.
2. Create a distance[] array and initialize all distances to INF, except the source node to
0.
3. Use a min-heap priority queue to process nodes by shortest distance.
4. For each node, check all neighbors and update their distances if a shorter path is
found.
5. Push updated neighbors into the queue for further processing.
6. After the loop, print shortest distances from the source to all other nodes.
7. In main(), build a graph with 5 nodes and weighted edges.
8. Call sssp(0) to compute shortest paths from node 0.
9. End.
b)
1. Define a 2D matrix dist[i][j] representing shortest distance from node i to j, initially
using direct edge weights.
2. Set dist[i][i] = 0 for all nodes (distance to itself is zero).
3. Run 3 nested loops with k, i, j to check if path i → k → j is shorter than direct i → j.
4. If dist[i][k] + dist[k][j] < dist[i][j], update dist[i][j].
5. After completion, dist[i][j] contains the shortest distance from every node i to every
node j.
6. In main(), build the graph by assigning weights to valid edges, leaving others as INF.
7. Call floyd() to compute all pairs shortest paths.
8. Print the final distance matrix.
97
Aim :
a) To write a C++ program to implement Single Source shortest path algorithm.
b) To write a C++ program to implement All pair shortest path algorithm.
Software Required:
VSCODE(C++compiler)
Theory:
The Single Source Shortest Path (SSSP) algorithm finds the shortest paths from a given
source node to all other nodes in a weighted graph. A commonly used algorithm for this is
Dijkstra’s Algorithm, which works efficiently with non-negative edge weights. It uses a priority
queue to always explore the nearest unvisited node and updates the shortest known distances
to its neighbors. This greedy approach ensures that once a node’s shortest path is found, it is
final.
The All Pairs Shortest Path (APSP) algorithm computes the shortest paths between every pair
of nodes in a graph. The Floyd-Warshall Algorithm is a classic solution for this, using dynamic
programming. It repeatedly updates a distance matrix by checking if going through an
intermediate node offers a shorter path between two nodes. It works on both directed and
undirected graphs, with positive or negative weights, as long as there are no negative cycles.
Coding:
a) #include <iostream>
#include <queue>
#include <vector>
#include <climits>
#define INF INT_MAX
using namespace std;
void sssp(int start, vector<vector<pair<int,int>>> &graph, int num){
vector<int> distance(num, INF);
distance[start]=0;
priority_queue<pair<int,int>, vector<pair<int,int>>, greater<>> pq;
pq.push({0,start});
while(!pq.empty()){
98
Output:
a)
Shortest distance from node 0 to :
Node 0 : 0
Node 1 : 2
Node 2 : 3
Node 3 : 9
Node 4 : 6
99
int main(){
int numnodes=5;
vector<vector<pair<int,int>>> graph(numnodes);
graph[0].push_back({1, 2});
graph[0].push_back({2, 4});
graph[1].push_back({2, 1});
graph[1].push_back({3, 7});
100
101
graph[2].push_back({4, 3});
graph[3].push_back({4, 1});
sssp(0,graph,numnodes);
return 0;
}
b)
#include <iostream>
#include <vector>
#include<climits>
#define INF INT_MAX
using namespace std;
void floyd(vector<vector<int>>& dist, int n){
int i,j,k;
for(k=0;k<n;k++){
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(dist[i][k]<INF && dist[k][j]<INF)
dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);
}
}
}
}
int main(){
int n =4;
vector<vector<int>> dist(n, vector<int>(n, INF));
for(int i=0;i<n;i++){
dist[i][i]=0;
}
dist[0][1] = 3;
dist[0][2] = 10;
102
Output:
b)
Shortest distances between all pairs:
0123
00346
17013
26902
34780
103
dist[1][2] = 1;
dist[2][3] = 2;
dist[3][0] = 4;
floyd(dist, n);
cout << "Shortest distances between all pairs:\n";
cout<<" 0 1 2 3"<<endl;
for (int i = 0; i < n; ++i) {
cout<<i<<" ";
for (int j = 0; j < n; ++j) {
if (dist[i][j] == INF)
cout << "INF ";
else
cout << dist[i][j] << " ";
}
cout << endl;
}
return 0;
}
Result :
Hence,the above programs have been executed and verified successfully.
104
Algorithm:
1. Create a structure Edge to store two nodes and a weight for each edge.
2. Store all graph edges in a vector and sort them by weight (smallest first).
3. Initialize a Disjoint Set Union (DSU) to keep track of connected components.
4. For each sorted edge, check if the two vertices are in different sets using
find().
5. If they are, add the edge to the MST and unite the sets using unite().
6. Accumulate the edge weights to compute total MST cost.
7. After processing all edges, print the selected MST edges and the total weight.
8. The MST will have exactly V-1 edges if the graph is connected.
105
Aim:
To write a C++ program to find the minimal Spanning tree for a graph.
Software Required:
VSCODE(C++ compiler)
Theory:
A Minimum Spanning Tree (MST) is a subset of the edges of a connected, weighted
graph that connects all the vertices with minimum total edge weight and no cycles. Among
several algorithms, Kruskal’s Algorithm is commonly used, which works by sorting all edges
by weight and adding the smallest edge that doesn’t form a cycle, until all vertices are
connected.
Kruskal's algorithm uses the Disjoint Set Union (DSU) or Union-Find structure to efficiently
detect cycles while adding edges. The MST always has exactly V - 1 edges for a graph with V
vertices. This algorithm works well for sparse graphs and has a time complexity of O(E log E)
due to edge sorting.
Coding:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct Edge{
int u,v,weight;
};
bool compare(Edge a,Edge b){
return a.weight<b.weight;
}
class Disjoint{
vector<int> parent, rank;
public:
Disjoint(int v){
parent.resize(v);
106
Output:
Minimum Spanning Tree edges:
3-4:2
2-3:4
0-3:5
0 - 1 : 10
Total weight of MST: 21
107
rank.resize(v,0);
for(int i=0; i<v;i++)
parent[i]=i;
}
int find(int x){
if(parent[x]!=x)
parent[x]= find(parent[x]);
return parent[x];
}
bool unite(int u,int v){
int rootu=find(u);
int rootv=find(v);
if(rootu==rootv) return false;
if(rank[rootu]>rank[rootv])
parent[rootv]=rootu;
else if(rank[rootv]<rank[rootu])
parent[rootu]=rootv;
else{
parent[rootu]=rootv;
rank[rootv++];
}
return true;
}
};
int main(){
vector<Edge> edges;
int v=5;
edges={
{0 ,1,10},
{0, 2, 6},
108
109
{0 ,3, 5},
{1, 3 ,15},
{2 ,3, 4},
{1 ,2, 25},
{3, 4, 2}};
sort(edges.begin(),edges.end(),compare);
vector<Edge> mst;
Disjoint d(v);
int total=0;
for(Edge e: edges){
if (d.unite(e.u,e.v))
{
mst.push_back(e);
total+=e.weight;
}
}
cout << "\nMinimum Spanning Tree edges:\n";
for(Edge e : mst) {
cout << e.u << " - " << e.v << " : " << e.weight << endl;
}
cout << "Total weight of MST: " << total << endl;
return 0;
}
Result :
Hence,the above programs have been executed and verified successfully.
110
Algorithm:
a)
1. Start at the first element of the array.
2. Compare the current element with the target value.
3. If it matches, return the current index.
4. If it doesn't match, move to the next element.
5. Repeat until the end of the array.
6. If no match is found, return -1.
b)
1. Start with the entire sorted array.
2. Find the middle element.
3. If it matches the target, return the middle index.
4. If the target is smaller, repeat the search in the left half.
5. If the target is larger, repeat the search in the right half.
6. Continue until the element is found or the search space is empty.
7. If not found, return -1.
111
Aim:
To write a C++ program to implement (a)linear search and (b)binary search.
Software Required:
VSCODE(C++ compiler)
Theory:
Linear Search is a simple search algorithm that sequentially checks each element of
the array or list until the target element is found or the list ends. It does not require the array to
be sorted and works on any kind of data. Although easy to implement, it is not efficient for
large datasets, with a time complexity of O(n) where n is the number of elements.
Binary Search, on the other hand, is a much faster search algorithm but requires the
input array to be sorted. It works by repeatedly dividing the search interval in half: comparing
the middle element to the target, and deciding whether to search the left or right half. This
divide-and-conquer approach results in a time complexity of O(log n), making it significantly
faster than linear search for large sorted data.
Coding:
a)
#include<iostream>
using namespace std;
int linearSearch(int arr[], int n, int target) {
for (int i = 0; i < n; i++) {
if (arr[i] == target) {
return i;
}
}
return -1;
}
int main() {
int arr[] = {5, 2, 9, 1, 5, 6};
112
Output:
a) Element found at index: 0
b) Element found at index: 2
113
int target = 5;
int n = sizeof(arr)/sizeof(arr[0]);
int result = linearSearch(arr, n, target);
if (result != -1)
cout << "Element found at index: " << result << endl;
else
cout << "Element not found" << endl;
return 0;
}
b)
#include<iostream>
using namespace std;
int binarySearch(int arr[], int n, int target) {
int low = 0, high = n - 1;
while (low <= high) {
int mid = low + (high - low) / 2;
if (arr[mid] == target) return mid;
if (arr[mid] > target) high = mid - 1;
else low = mid + 1;
}
return -1;
}
int main() {
int arr[] = {1, 2, 5, 5, 6, 9};
int target = 5;
int n = sizeof(arr)/sizeof(arr[0]);
int result = binarySearch(arr, n, target);
if (result != -1)
cout << "Element found at index: " << result << endl;
else
114
115
Result :
Hence,the above programs have been executed and verified successfully.
116
Algorithm:
a)
1. Start from the second element in the array.
2. Compare it with elements before it and shift larger elements one position to the right.
3. Insert the current element into its correct position.
4. Repeat for all elements until the array is sorted.
b)
1. Divide the array into two halves.
2. Recursively sort each half.
3. Merge the two sorted halves into one sorted array.
4. Repeat until the entire array is merged and sorted.
c)
1. Select a pivot element from the array.
2. Partition the array such that elements less than pivot go left, and greater go right.
3. Recursively apply the same process to the left and right subarrays.
4. Repeat until all subarrays are sorted.
d)
1. Build a max-heap from the array.
2. Swap the root (maximum) element with the last element.
3. Reduce heap size and heapify the root again.
4. Repeat until the heap size is reduced to one and the array is sorted.
117
Aim:
To write a C++ program to implement the following:
a) Insertion sort
b) Merge sort
c) Quick sort
d) Heap sort
Software Required:
VSCODE(C++ compiler)
Theory:
Insertion Sort is a simple comparison-based sorting algorithm that builds the final
sorted array one element at a time. It works by taking one element from the unsorted part and
inserting it into the correct position in the sorted part. This process is repeated until all elements
are sorted. Insertion sort is efficient for small datasets or nearly sorted data and works in-place
with O(1) auxiliary space. However, its time complexity is O(n²) in the worst case, making it
less suitable for large datasets.
Merge Sort is a divide-and-conquer algorithm that divides the input array into two
halves, recursively sorts them, and then merges the sorted halves. This merging process ensures
that the final array is sorted. The key advantage of merge sort is its consistent time complexity
of O(n log n) for best, worst, and average cases. However, it requires additional memory space
proportional to the array size (O(n)) due to the temporary arrays used during the merge process.
Merge sort is stable and well-suited for sorting linked lists and large datasets.
Quick Sort is an efficient and widely-used divide-and-conquer sorting algorithm. It
works by selecting a ‘pivot’ element and partitioning the array such that elements smaller than
the pivot are on the left and those greater are on the right. The process is then applied
recursively to the subarrays. Quick sort has an average-case time complexity of O(n log n), but
it can degrade to O(n²) in the worst case if poor pivot choices are made. Despite this, it is often
faster in practice than other O(n log n) algorithms and works in-place with O(log n) auxiliary
space.
Heap Sort is a comparison-based sorting technique based on a binary heap data
structure. It first builds a max-heap from the input data, then repeatedly extracts the maximum
element from the heap and places it at the end of the array. This process continues until the
heap is empty and the array is sorted. Heap sort has a time complexity of O(n log n) for all
cases and requires only a constant amount of extra space (O(1)). Although it is not stable, heap
sort is very efficient for large data sets and does not require recursion.
Coding:
118
Output:
a)
Original array:
13
32
26
9
35
18
The elements are:
9
13
18
26
32
35
119
a)#include<iostream>
#include<vector>
using namespace std;
void insertion(vector<int>&arr){
int n=arr.size();
for(int i=0;i<n;i++){
int key=arr[i];
int j=i-1;
while(j>=0 && arr[j]>key){
arr[j+1]=arr[j];
j--;
}
arr[j+1]=key;
}
}
int main(){
vector<int>arr ={13,32,26,9,35,18};
vector<int>inserted =arr;
insertion(inserted);
cout<<"Original array: "<<endl;
for(int i=0;i<arr.size();i++){
cout<<"\t"<<arr[i] <<endl;
}
cout<<"The elements are: "<<endl;
for(int i=0;i<arr.size();i++){
cout<<"\t"<<inserted[i] <<endl;
}
return 0;
}
120
Output:
b) 1 2 5 5 6 9
c) 1 5 7 8 9 10
d) 1 3 4 5 10
121
b)
#include <iostream>
using namespace std;
void merge(int arr[], int l, int m, int r) {
int n1 = m - l + 1, n2 = r - m;
int L[n1], R[n2];
for (int i = 0; i < n1; i++) L[i] = arr[l + i];
for (int i = 0; i < n2; i++) R[i] = arr[m + 1 + i];
int i = 0, j = 0, k = l;
while (i < n1 && j < n2)
arr[k++] = (L[i] <= R[j]) ? L[i++] : R[j++];
while (i < n1) arr[k++] = L[i++];
while (j < n2) arr[k++] = R[j++];
}
int main() {
int arr[] = {5, 2, 9, 1, 5, 6};
int n = sizeof(arr)/sizeof(arr[0]);
mergeSort(arr, 0, n - 1);
for (int i = 0; i < n; i++) cout << arr[i] << " ";
}
122
123
c)
#include <iostream>
using namespace std;
int partition(int arr[], int low, int high) {
int pivot = arr[high], i = low - 1;
for (int j = low; j < high; j++)
if (arr[j] < pivot) swap(arr[++i], arr[j]);
swap(arr[i + 1], arr[high]);
return i + 1;
}
void quickSort(int arr[], int low, int high) {
if (low < high) {
int pi = partition(arr, low, high);
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
int main() {
int arr[] = {10, 7, 8, 9, 1, 5};
int n = sizeof(arr)/sizeof(arr[0]);
quickSort(arr, 0, n - 1);
for (int i = 0; i < n; i++) cout << arr[i] << " ";
}
d)
#include <iostream>
using namespace std;
Result :
Hence,the above programs have been executed and verified successfully.
126