Professional Documents
Culture Documents
Summer Internship Report ON "C++ and Data Structure" Submitted in Partial Fulfilment The Requirements For The Degree of
Summer Internship Report ON "C++ and Data Structure" Submitted in Partial Fulfilment The Requirements For The Degree of
ON
BACHELORS OF COMPUTER
APPLICATIONS
Roll no. 52
The most awaited moment of any endeavor is successful completion, but nothing can be
done successfully if done alone. Success is the outcome of the contribution and
consistent help of various persons and we thank those who helped us in the successful
completion of this project.
Primarily I would like to thank Dr. Sonal Sharma, Dean USCS for providing a healthy
and encouraging environment to study.
I profusely thankful to the department of computing Science, and Dr. Sameer Dev
Sharma, HOD, and my Project Mentor Mr. Parminder Singh. I am also thankful to
my mentor Mr. Akshay Rawat sir for guiding me throughout the internship period. He
has been generous enough to provide me an opportunity and accepting my candidature
for the most valuable guidance and affordable treatment given to us at every stage to
boost my morale.
.
I hereby declare that the internship report entitled C++ AND DATA STRUCTURE is
submitted by Sagar Singh Rawat to Uttaranchal Institute of Management. The
internship was done under the guidance of Mr. Parminder Singh sir. I further declare
that the work reported in this internship has not been submitted and will not be
submitted, either in part or in full, for the award of any other degree or diploma in this
university or any other university or institute.
ii
CERTIFICATE OF ORIGINALITY
This is to certify that the internship entitled “C++ AND DATA STRUCTURE” by
Sagar Singh Rawat has been submitted in the partial fulfillment of the requirements for
the award of the degree of BCA from Uttaranchal University, Dehradun. The results
embodied in this project have not been submitted to any other University or Institution
for the record of any degree.
Assistant Professor
Uttaranchal University
Dehradun
iii
COMPANY CERTIFICATE
iv
TABLE OF CONTENTS
DECALARATION ii
CERTIFICATE OF ORIGINALITY iii
COMPANY'S CERTIFICATE iv
TABLE OF CONTENTS v
1 INTRODUCTION 6
1.1 Objectives 6
2 COMPANY PROFILE 7
2.1 Services 7
2.2 Aim / Vision / Mission 7
v
Report Introduction: C++ and Data Structures
This report serves as an in-depth exploration of the pivotal roles played by C++
programming language and Data Structures within the domain of computer
science. C++ is a versatile language renowned for its amalgamation of
procedural and object-oriented programming paradigms. When coupled with a
profound understanding of Data Structures—specialized formats facilitating
efficient data organization—these concepts collectively form the cornerstone of
effective software development.
This report aims to deeply explore the synergy between C++ and Data
Structures in computer science. It focuses on achieving a thorough
understanding of C++ fundamentals, emphasizing syntax and versatility.
Simultaneously, the report aims to instil proficiency in various data structures,
elucidating strengths and optimal applications.
6
About - SLOG Solutions Pvt. Ltd.
SLOG Solutions Pvt. Ltd. Dehradun – Slog Solutions Private Limited, an ISO
9001:2015 certified, Uttarakhand's only MSME certified training company in
the engineering domain. Established in 2018, Slog offers various technologies
training to individuals all over India. We provide exceptional quality training of
each and every technology through our skilled trainers who are constantly
evolving to achieve their highest potential. Slog offers three types of services in
the engineering field
SLOG Dehradun – The reputed training institute in Dehradun has provided a
powerful training tool that can be used directly where training is required, Slog
has delivered thousands of skilled professionals to the industry. The Skill
Development Company offers an in-depth learning and industry compliance
training and certification to the individuals and corporate clients. Our company
providing great opportunities in the growing field to the students. We have best
career boosting options for the learners.
Mission Statement
SLOG Solutions Pvt. Ltd. Dehradun – The reputed training institute in
Dehradun has provided a powerful training tool that can be used directly where
training is required, Slog has delivered thousands of skilled professionals to the
industry.
Vision Statement
SLOG Solutions Pvt. Ltd. Dehradun – The reputed training institute in
Dehradun has provided a powerful training tool that can be used directly where
training is required, Slog has delivered thousands of skilled professionals to the
industry.
7
C++ And Data Structure
C++ Introduction
C++ can be found in today's operating systems, Graphical User Interfaces, and
embedded systems.
C++ is portable and can be used to develop applications that can be adapted to
multiple platforms.
8
C++ Syntax
Let's break up the following code to understand it better:
Example
#include <iostream>
using namespace std;
int main() {
cout << "Hello World!";
return 0;
}
Omitting Namespace
You might see some C++ programs that runs without the standard namespace
library. The using namespace std line can be omitted and replaced with the std
keyword, followed by the :: operator for some objects:
Example
#include <iostream>
int main() {
return 0;
9
C++ Variables
Variables are containers for storing data values.
In C++, there are different types of variables (defined with different keywords),
for example:
Syntax
Where type is one of C++ types (such as int), and variableName is the name of
the variable (such as x or myName). The equal sign is used to assign values to
the variable.
10
You can also declare a variable without assigning the value, and assign the
value later:
int myNum;
myNum = 15;
Note that if you assign a new value to an existing variable, it will overwrite the
previous value:
Other Types
A demonstration of other data types:
Example
11
C++ Identifiers
All C++ variables must be identified with unique names.
Identifiers can be short names (like x and y) or more descriptive names (age,
sum, totalVolume).
Example
// Good
int m = 60;
Constants
When you do not want others (or yourself) to change existing variable values,
use the const keyword (this will declare the variable as "constant", which means
unchangeable and read-only):
Example
Example
13
C++ Operators
Operators are used to perform operations on variables and values.
In the example below, we use the + operator to add together two values:
Example
Example
int sum1 = 100 + 50; // 150 (100 + 50)
int sum2 = sum1 + 250; // 400 (150 + 250)
int sum3 = sum2 + sum2; // 800 (400 + 400)
Arithmetic operators
Assignment operators
Comparison operators
Logical operators
Bitwise operators
14
Arithmetic Operators
Assignment Operators
In the example below, we use the assignment operator (=) to assign the value 10
to a variable called x:
Example
int x = 10;
The addition assignment operator (+=) adds a value to a variable:
Example
int x = 10;
x += 5;
-= x -= 3 x=x-3
*= x *= 3 x=x*3
/= x /= 3 x=x/3
%= x %= 3 x=x%3
&= x &= 3 x=x&3
|= x |= 3 x=x|3
^= x ^= 3 x=x^3
>>= x >>= 3 x = x >> 3
Comparison Operators
Comparison operators are used to compare two values (or variables). This is
important in programming, because it helps us to find answers and make
decisions.
The return value of a comparison is either 1 or 0, which means true (1) or false
(0). These values are known as Boolean values, and you will learn more about
them in the Booleans and If..Else chapter.
In the following example, we use the greater than operator (>) to find out if 5 is
greater than 3:
Example
int x = 5;
int y = 3;
cout << (x > y); // returns 1 (true) because 5 is greater than 3
16
Operator Name Example
== Equal to x == y
!= Not equal x != y
> Greater than x>y
< Less than x<y
>= Greater than or equal to x >= y
Logical Operators
As with comparison operators, you can also test for true (1) or false (0) values
with logical operators.
Logical operators are used to determine the logic between variables or values:
! Logical not Reverse the result, !(x < 5 && x < 10)
returns false if the
result is true
17
C++ Conditions and If Statements
You already know that C++ supports the usual logical conditions from
mathematics:
Syntax
if (condition) {
// block of code to be executed if the condition is true
}
Example
if (20 > 18) {
cout << "20 is greater than 18";
}
Example
int x = 20;
int y = 18;
if (x > y) {
cout << "x is greater than y";
}
18
The else Statement
Use the else statement to specify a block of code to be executed if the condition
is false.
Syntax
if (condition) {
// block of code to be executed if the condition is true
} else {
// block of code to be executed if the condition is false
}
Example
int time = 20;
if (time < 18) {
cout << "Good day.";
} else {
cout << "Good evening.";
}
// Outputs "Good evening."
Syntax
if (condition1) {
// block of code to be executed if condition1 is true
} else if (condition2) {
// block of code to be executed if the condition1 is false and condition2 is true
} else {
// block of code to be executed if the condition1 is false and condition2 is false
}
Example
int time = 22;
if (time < 10) {
cout << "Good morning.";
} else if (time < 20) {
cout << "Good day.";
} else {
cout << "Good evening.";
}
// Outputs "Good evening."
19
C++ Loops
Loops can execute a block of code as long as a specified condition is reached.
Loops are handy because they save time, reduce errors, and they make code
more readable.
The while loop loops through a block of code as long as a specified condition is
true:
Syntax
while (condition) {
// code block to be executed
}
In the example below, the code in the loop will run, over and over again, as long
as a variable (i) is less than 5:
Example
int i = 0;
while (i < 5) {
cout << i << "\n";
i++;
}
The do/while loop is a variant of the while loop. This loop will execute the code
block once, before checking if the condition is true, then it will repeat the loop
as long as the condition is true.
Syntax
do {
// code block to be executed
}
while (condition);
Example
int i = 0;
20
do {
cout << i << "\n";
i++;
}
while (i < 5);
Syntax
for (statement 1; statement 2; statement 3) {
// code block to be executed
}
Statement 1 is executed (one time) before the execution of the code block.
Statement 3 is executed (every time) after the code block has been executed.
Example
for (int i = 0; i < 5; i++) {
cout << i << "\n";
}
Nested Loops
It is also possible to place a loop inside another loop. This is called a nested
loop.The "inner loop" will be executed one time for each iteration of the "outer
loop":
Example
// Outer loop
for (int i = 1; i <= 2; ++i) {
cout << "Outer: " << i << "\n"; // Executes 2 times
// Inner loop
for (int j = 1; j <= 3; ++j) {
cout << " Inner: " << j << "\n"; // Executes 6 times (2 * 3)
}
}
21
C++ Break and Continue
C++ Break
You have already seen the break statement used in an earlier chapter of this
tutorial. It was used to "jump out" of a switch statement.
Example
for (int i = 0; i < 10; i++) {
if (i == 4) {
break;
}
cout << i << "\n";
}
C++ Continue
The continue statement breaks one iteration (in the loop), if a specified
condition occurs, and continues with the next iteration in the loop.
Example
for (int i = 0; i < 10; i++) {
if (i == 4) {
continue;
}
cout << i << "\n";
}
C++ Functions
A function is a block of code which only runs when it is called. You can pass
data, known as parameters, into a function. Functions are used to perform
certain actions, and they are important for reusing code: Define the code once,
and use it many times.
22
Create a Function
Syntax
void myFunction() {
// code to be executed
}
Call a Function
Declared functions are not executed immediately. They are "saved for later use",
and will be executed later, when they are called.
To call a function, write the function's name followed by two parentheses () and
a semicolon ;
In the following example, myFunction() is used to print a text (the action), when
it is called:
Example
Inside main, call myFunction():
// Create a function
void myFunction() {
cout << "I just got executed!";
}
int main() {
myFunction(); // call the function
return 0;
}
23
A function can be called multiple times:
Example
void myFunction() {
cout << "I just got executed!\n";
}
int main() {
myFunction();
myFunction();
myFunction();
return 0;
}
// I just got executed!
// I just got executed!
// I just got executed!
Declaration: the return type, the name of the function, and parameters (if any)
Example
int main() {
myFunction();
return 0;
}
void myFunction() {
cout << "I just got executed!";
}
// Error
24
Parameters and Arguments
Parameters are specified after the function name, inside the parentheses. You
can add as many parameters as you want, just separate them with a comma:
Syntax
void functionName(parameter1, parameter2, parameter3) {
// code to be executed
}
Example
void myFunction(string fname) {
cout << fname << " Refsnes\n";
}
int main() {
myFunction("Liam");
myFunction("Jenny");
myFunction("Anja");
return 0;
}
// Liam Refsnes
// Jenny Refsnes
// Anja Refsnes
Function Overloading
With function overloading, multiple functions can have the same name with
different parameters:
Example
int plusFuncInt(int x, int y) {
return x + y;
}
double plusFuncDouble(double x, double y) {
25
return x + y;
}
int main() {
int myNum1 = plusFuncInt(8, 5);
double myNum2 = plusFuncDouble(4.3, 6.26);
cout << "Int: " << myNum1 << "\n";
cout << "Double: " << myNum2;
return 0;
}
C++ Arrays
Arrays are used to store multiple values in a single variable, instead of declaring
separate variables for each value.
To declare an array, define the variable type, specify the name of the array
followed by square brackets and specify the number of elements it should store:
string cars[4];
We have now declared a variable that holds an array of four strings. To insert
values to it, we can use an array literal - place the values in a comma-separated
list, inside curly braces:
Example
string cars[4] = {"Volvo", "BMW", "Ford", "Mazda"};
cout << cars[0];
// Outputs Volvo
26
Change an Array Element
To change the value of a specific element, refer to the index number:
cars[0] = "Opel";
Example
string cars[4] = {"Volvo", "BMW", "Ford", "Mazda"};
cars[0] = "Opel";
cout << cars[0];
// Now outputs Opel instead of Volvo
Example
string cars[5] = {"Volvo", "BMW", "Ford", "Mazda", "Tesla"};
for (int i = 0; i < 5; i++) {
cout << cars[i] << "\n";
}
Example
string cars[5] = {"Volvo", "BMW", "Ford", "Mazda", "Tesla"};
for (int i = 0; i < 5; i++) {
cout << i << " = " << cars[i] << "\n";
}
And this example shows how to loop through an array of integers:
Example
int myNumbers[5] = {10, 20, 30, 40, 50};
for (int i = 0; i < 5; i++) {
cout << myNumbers[i] << "\n";
}
The for-each Loop
There is also a "for-each loop", which is used exclusively to loop through
elements in an array:
Syntax
for (type variableName : arrayName) {
// code block to be executed
27
}
Example
int myNumbers[5] = {10, 20, 30, 40, 50};
for (int i : myNumbers) {
cout << i << "\n";
}
C++ Structures
Structures (also called structs) are a way to group several related variables into
one place. Each variable in the structure is known as a member of the structure.
Unlike an array, a structure can contain many different data types (int, string,
bool, etc.).
Create a Structure
To create a structure, use the struct keyword and declare each of its members
inside curly braces.
Example:
struct { // Structure declaration
int myNum; // Member (int variable)
string myString; // Member (string variable)
} myStructure; // Structure variable
Access Structure Members
Example
Assign data to members of a structure and print it:
28
One Structure in Multiple Variables
You can use a comma (,) to use one structure in many variables:
struct {
int myNum;
string myString;
} myStruct1, myStruct2, myStruct3; // Multiple structure variables separated
with commas
Example
Use one structure to represent two cars:
struct {
string brand;
string model;
int year;
} myCar1, myCar2; // We can add variables by separating them with a comma
here
C++ Pointers
Creating Pointers
You learned from the previous chapter, that we can get the memory address of a
variable by using the & operator:
Example
string food = "Pizza"; // A food variable of type string
29
cout << food; // Outputs the value of food (Pizza)
cout << &food; // Outputs the memory address of food (0x6dfed4)
A pointer however, is a variable that stores the memory address as its value.
A pointer variable points to a data type (like int or string) of the same type, and
is created with the * operator. The address of the variable you're working with is
assigned to the pointer:
Example
string food = "Pizza"; // A food variable of type string
string* ptr = &food; // A pointer variable, with the name ptr, that stores the
address of food
C++ OOP
C++ What is OOP?
OOP stands for Object-Oriented Programming. Procedural programming is
about writing procedures or functions that perform operations on the data, while
object-oriented programming is about creating objects that contain both data
and functions.
30
OOP makes it possible to create full reusable applications with less code
and shorter development time.
Class Objects
Fruits Mango
Apple
Banana
So, a class is a template for objects, and an object is an instance of a class.
When the individual objects are created, they inherit all the variables and
functions from the class.
C++ Classes and Objects
C++ Classes/Objects
Everything in C++ is associated with classes and objects, along with its
attributes and methods. For example: in real life, a car is an object. The car has
attributes, such as weight and color, and methods, such as drive and brake.
Attributes and methods are basically variables and functions that belongs to the
class. These are often referred to as "class members".
A class is a user-defined data type that we can use in our program, and it works
as an object constructor, or a "blueprint" for creating objects.
Create a Class
To create a class, use the class keyword:
Example
Create a class called "MyClass":
31
int myNum; // Attribute (int variable)
string myString; // Attribute (string variable)
};
Create an Object
In C++, an object is created from a class. We have already created the class
named MyClass, so now we can use this to create objects. To create an object of
MyClass, specify the class name, followed by the object name.
To access the class attributes (myNum and myString), use the dot syntax (.) on
the object:
Example
Create an object called "myObj" and access the attributes:
int main() {
MyClass myObj; // Create an object of MyClass
Class Methods
32
Outside class definition
In the following example, we define a function inside the class, and we name it
"myMethod".
Example
class MyClass { // The class
public: // Access specifier
void myMethod() { // Method/function defined inside the class
cout << "Hello World!";
}
};
int main() {
MyClass myObj; // Create an object of MyClass
myObj.myMethod(); // Call the method
return 0;
}
Parameters
You can also add parameters:
Example
#include <iostream>
using namespace std;
class Car {
public:
int speed(int maxSpeed);
};
int main() {
Car myObj; // Create an object of Car
cout << myObj.speed(200); // Call the method with an argument
return 0;
}
Access Specifiers
33
By now, you are quite familiar with the public keyword that appears in all of our
class examples:
Example
class MyClass { // The class
public: // Access specifier
// class members goes here
};
The public keyword is an access specifier. Access specifiers define how the
members (attributes and methods) of a class can be accessed. In the example
above, the members are public - which means that they can be accessed and
modified from outside the code.
Example
class MyClass {
public: // Public access specifier
int x; // Public attribute
private: // Private access specifier
int y; // Private attribute
};
int main() {
MyClass myObj;
myObj.x = 25; // Allowed (public)
myObj.y = 50; // Not allowed (private)
return 0;
}
//If you try to access a private member, an error occurs:
error: y is private.
34
C++ Encapsulation
Encapsulation
Example
#include <iostream>
using namespace std;
class Employee {
private:
// Private attribute
int salary;
public:
// Setter
void setSalary(int s) {
salary = s;
}
// Getter
int getSalary() {
return salary;
}
};
int main() {
Employee myObj;
myObj.setSalary(50000);
cout << myObj.getSalary();
return 0;
}
35
C++ Inheritance
Inheritance
In C++, it is possible to inherit attributes and methods from one class to another.
We group the "inheritance concept" into two categories:
derived class (child) - the class that inherits from another class
base class (parent) - the class being inherited from
To inherit from a class, use the : symbol.
In the example below, the Car class (child) inherits the attributes and methods
from the Vehicle class (parent):
Example
// Base class
class Vehicle {
public:
string brand = "Ford";
void honk() {
cout << "Tuut, tuut! \n" ;
}
};
// Derived class
class Car: public Vehicle {
public:
string model = "Mustang";
};
int main() {
Car myCar;
myCar.honk();
cout << myCar.brand + " " + myCar.model;
return 0;
}
C++ Polymorphism
36
Polymorphism
Polymorphism means "many forms", and it occurs when we have many classes
that are related to each other by inheritance.
For example, think of a base class called Animal that has a method called
animalSound(). Derived classes of Animals could be Pigs, Cats, Dogs, Birds -
And they also have their own implementation of an animal sound (the pig oinks,
and the cat meows, etc.):
Example
// Base class
class Animal {
public:
void animalSound() {
cout << "The animal makes a sound \n";
}
};
// Derived class
class Pig : public Animal {
public:
void animalSound() {
cout << "The pig says: wee wee \n";
}
};
// Derived class
class Dog : public Animal {
public:
void animalSound() {
cout << "The dog says: bow wow \n";
}
};
37
C++ DSA
In this article, we will explore the fundamentals of C++ DSA, including Data
Structures and Algorithms, their importance, and how they can be used to solve
real-world problems.
For example, consider a program that needs to search for a particular item in a
large dataset. Using an efficient search Algorithm like Binary Search can
significantly reduce the search time and improve the performance of the
program. Similarly, using an appropriate Data Structure like a Hash Table can
38
significantly reduce the time required to Insert, Search, and Delete items from a
dataset.
Binary search
The binary search algorithm is a divide and conquer algorithm that you can use
to search for and find elements in a sorted array.
The algorithm is fast in searching for elements because it removes half of the
array every time the search iteration happens.
So instead of searching through the whole array, the algorithm removes half of
the array where the element to be searched for can't be found. It does this
continuously until the element is found.
In a case where the element to be searched for doesn't exist, it returns a value of
-1. If the element exists, then it returns the index of the element.
If the explanations above seem complex, then you should check out this visual
guide on how the binary search algorithm works.
#include <iostream>
using namespace std;
if (number_to_search_for == array[mid]){
return mid;
}
return -1;
}
int main(void) {
int arrayOfNums[] = {2,4,7,9,10,13,20};
if (result == -1){
printf("Element doesn't exist in the array");
}
else{
printf("The index of the element is %d", result);
}
Step 1: Declare the variables and input all elements of an array in sorted order
(ascending or descending).
Step 3: Now compare the target elements with the middle element of the array.
And if the value of the target element is matched with the middle element,
return the middle element's position and end the search process.
Step 4: If the target element is less than the middle element, we search the
elements into the lower half of an array.
Step 5: If the target element is larger than the middle element, we need to search
the element into the greater half of the array.
Step 6: We will continuously repeat steps 4, 5, and 6 till the specified element is
not found in the sorted array.
40
Merge Sort
Merge Sort is one of the most popular sorting algorithms that is based on the
principle of Divide and Conquer Algorithm.
Divide
If q is the half-way point between p and r, then we can split the subarray A[p..r]
into two arrays A[p..q] and A[q+1, r].
Conquer
In the conquer step, we try to sort both the subarrays A[p..q] and A[q+1, r]. If
we haven't yet reached the base case, we again divide both these subarrays and
try to sort them.
Combine
When the conquer step reaches the base step and we get two sorted subarrays
A[p..q] and A[q+1, r] for array A[p..r], we combine the results by creating a
sorted array A[p..r] from two sorted subarrays A[p..q] and A[q+1, r].
41
#1) The list to be sorted is divided into two arrays of equal length by dividing
the list on the middle element. If the number of elements in the list is either 0 or
1, then the list is considered sorted.
#3) The sorted sublists are then combined or merged together to form a
complete sorted list.
General Algorithm
The general pseudo-code for the merge sort technique is given below.
#include <iostream>
42
k++;
i++;
}
else
{
temp[k] = a[j];
k++;
j++;
}
}
int main()
{
int n, i;
cout<<"\nEnter the number of data element to be sorted: ";
cin>>n;
int arr[n];
for(i = 0; i < n; i++)
{
cout<<"Enter element "<<i+1<<": ";
cin>>arr[i];
}
MergeSort(arr, 0, n-1);
return 0;
}
Unlike arrays, the linked list does not need to store data elements in contiguous
memory regions or blocks.
A linked list is composed of elements known as "Nodes" that are divided into
two parts. The first component is the part where we store the actual data, and the
second is a part where we store the pointer to the next node. This type of
structure is known as a "singly linked list."
44
1) Insertion
The linked list is expanded by the action of adding to it. Although it would seem
simple, given the linked list's structure, we know that every time a data item is
added, we must change the next pointers of the previous and next nodes of the
new item that we have added.
Where the new data item will be inserted is the second aspect to think about.
There are three places where a data item can be added to the linked list.
In this case, we are given a node and must add a new node behind it. The linked
list will seem as follows if node f is added to the linked list a->b->c->d->e after
node c:
In the third case, a new node is added to the end of the linked list. Take into
account the linked list below: a->b->c->d->e, with the addition of node f at the
end. After adding the node, the linked list will appear like this.
45
A linked list can be declared as a structure or as a class in C++. A linked list
declared as a structure is a classic C-style statement. A linked list is used as a
class in modern C++, mainly when using the standard template library.
Structure was used in the following application to declare and generate a linked
list. Its members will be data and a pointer to the following element.
C++ Program:
#include <iostream>
using namespace std;
struct Node
{
int data;
struct Node *next;
};
void push ( struct Node** head, int nodeData )
{
struct Node* newNode1 = new Node;
(*head) = newNode1;
}
void insertAfter ( struct Node* prevNode, int nodeData )
{
if ( prevNode == NULL )
{
cout << "the given previous node is required,cannot be NULL";
return;
}
struct Node* newNode1 =new Node;
newNode1 -> data = nodeData;
newNode1 -> next = prevNode -> next;
prevNode -> next = newNode1;
}
void append ( struct Node** head, int nodeData )
{
struct Node* newNode1 = new Node;
46
struct Node *last = *head;
newNode1 -> data = nodeData;
newNode1 -> next = NULL;
if ( *head == NULL )
{
*head = newNode1;
return;
}
while ( last -> next != NULL )
last = last -> next;
last -> next = newNode1;
return;
}
void displayList ( struct Node *node )
{
while ( node != NULL )
{
cout << node -> data << "-->";
node = node -> next;
}
if ( node== NULL)
cout<<"null";
}
int main ()
{
struct Node* head = NULL;
append ( &head, 15 );
push ( &head, 25 );
push ( &head, 35 );
append ( &head, 45 );
insertAfter ( head -> next, 55 );
return 0;
}
Output:
47
2) Deletion
Similar to insertion, deleting a node from a linked list requires many points
from which the node might be eliminated. We can remove the linked list's first,
last, or kth node at random. We must correctly update the next pointer and all
other linked list pointers in order to maintain the linked list after deletion.
C++ Program:
#include <iostream>
using namespace std;
struct Node {
int data;
struct Node* next;
};
Node* deletingFirstNode ( struct Node* head )
{
if ( head == NULL )
return NULL;
Node* tempNode = head;
head = head -> next;
delete tempNode;
return head;
}
Node* removingLastNode ( struct Node* head )
{
if ( head == NULL )
return NULL;
48
secondLast -> next = NULL;
return head;
}
void push ( struct Node** head, int newData )
{
struct Node* newNode1 = new Node;
newNode1 -> data = newData;
newNode1 -> next = ( *head );
( *head ) = newNode1;
}
int main()
{
Node* head = NULL;
push ( &head, 25 );
push ( &head, 45 );
push ( &head, 65);
push ( &head, 85 );
push ( &head, 95 );
Node* temp;
cout << "Linked list created " << endl; for ( temp = head; temp != NULL;
temp = temp -> next )
cout << temp->data << "-->";
if ( temp == NULL )
cout << "NULL" << endl;
head = deletingFirstNode (head);
cout << "Linked list after deleting head node" << endl; for ( temp = head;
temp != NULL; temp = temp -> next )
cout << temp->data << "-->";
if ( temp == NULL )
cout<<"NULL"<<endl;
head = removingLastNode (head);
cout << "Linked list after deleting last node" << endl; for ( temp = head;
temp != NULL; temp = temp -> next )
cout << temp -> data << "-->";
if ( temp == NULL )
cout << "NULL";
return 0;
}
Output:
49
Linked list created
95-->85-->65-->45-->25-->NULL
Linked list after deleting head node
85-->65-->45-->25-->NULL
Linked list after deleting last node
85-->65-->45-->NULL
Traversing through a linked list is very easy. It requires creating a temp node
pointing to the head of the list. If the temp node is not null, display its content
and move to the next node using temp next. Repeat the process till the temp
node becomes null. If the temp node is empty at the start, then the list contains
no item.
void PrintList() {
50
Circular Linked List In C++
A circular linked list can be a singly linked list or a doubly linked list. In a
doubly circular linked list, the previous pointer of the first node is connected to
the last node while the next pointer of the last node is connected to the first
node.
Declaration
We can declare a node in a circular linked list as any other node as shown
below:
struct Node
{
int data;
struct Node *next;
};
In order to implement the circular linked list, we maintain an external pointer
“last” that points to the last node in the circular linked list. Hence last->next will
point to the first node in the linked list.
By doing this we ensure that when we insert a new node at the beginning or at
the end of the list, we need not traverse the entire list. This is because the last
points to the last node while last->next points to the first node.
This wouldn’t have been possible if we had pointed the external pointer to the
first node.
Basic Operations
The circular linked list supports insertion, deletion, and traversal of the list. We
will discuss each of the operations in detail now.
Insertion
51
We can insert a node in a circular linked list either as a first node (empty list), in
the beginning, in the end, or in between the other nodes. Let us see each of these
insertion operations using a pictorial representation below.
When there are no nodes in circular list and the list is empty, the last pointer is
null, then we insert a new node N by pointing the last pointer to the node N as
shown above. The next pointer of N will point to the node N itself as there is
only one node. Thus N becomes the first as well as last node in the list.
N->next = last->next
Last->next = N
To insert a new node at the end of the list, we follow these steps:
Suppose we need to insert a new node N between N3 and N4, we first need to
traverse the list and locate the node after which the new node is to be inserted,
in this case, its N3.
52
Deletion
The deletion operation of the circular linked list involves locating the node that
is to be deleted and then freeing its memory.
For this we maintain two additional pointers curr and prev and then traverse the
list to locate the node. The given node to be deleted can be the first node, the
last node or the node in between. Depending on the location we set the curr and
prev pointers and then delete the curr node.
Traversal
Traversal is a technique of visiting each and every node. In linear linked lists
like singly linked list and doubly linked lists, traversal is easy as we visit each
node and stop when NULL is encountered.
However, this is not possible in a circular linked list. In a circular linked list, we
start from the next of the last node which is the first node and traverse each
node. We stop when we once again reach the first node.
C++ queue
In computer science we go for working on a large variety of programs. Each of
them has their own domain and utility. Based on the purpose and environment
of the program creation, we have a large number of data structures available to
choose from. One of them is 'queues. Before discussing about this data type let
us take a look at its syntax.
Syntax
template<class T, class Container = deque<T> > class queue;
This data structure works on the FIFO technique, where FIFO stands for First In
First Out. The element which was first inserted will be extracted at the first and
so on. There is an element called as 'front' which is the element at the front most
position or say the first position, also there is an element called as 'rear' which is
53
the element at the last position. In normal queues insertion of elements take at
the rear end and the deletion is done from the front.
Functions
With the help of functions, an object or variable can be played with in the field
of programming. Queues provide a large number of functions that can be used
or embedded in the programs. A list of the same is given below:
Function Description
(constructor) The function is used for the construction of a
queue container.
empty The function is used to test for the emptiness of
a queue. If the queue is empty the function
returns true else false.
size The function returns the size of the queue
container, which is a measure of the number of
elements stored in the queue.
front The function is used to access the front element
of the queue. The element plays a very
important role as all the deletion operations are
performed at the front element.
back The function is used to access the rear element
of the queue. The element plays a very
important role as all the insertion operations are
performed at the rear element.
push The function is used for the insertion of a new
element at the rear end of the queue.
pop The function is used for the deletion of element;
the element in the queue is deleted from the
front end.
emplace The function is used for insertion of new
elements in the queue above the current rear
element.
swap The function is used for interchanging the
contents of two containers in reference.
relational operators The non member function specifies the
relational operators that are needed for the
queues.
uses allocator<queue> As the name suggests the non member function
uses the allocator for the queues.
54
Example: A simple program to show the use of basic queue functions.
#include <iostream>
#include <queue>
using namespace std;
void showsg(queue <int> sg)
{
queue <int> ss = sg;
while (!ss.empty())
{
cout << '\t' << ss.front();
ss.pop();
}
cout << '\n';
}
int main()
{
queue <int> fquiz;
fquiz.push(10);
fquiz.push(20);
fquiz.push(30);
return 0;
}
Types of Queue
There are four different types of queue that are listed as follows -
55
Double Ended Queue (or Deque)
The major drawback of using a linear Queue is that insertion is done only from
the rear end. If the first three elements are deleted from the Queue, we cannot
insert more elements even though the space is available in a Linear Queue. In
this case, the linear Queue shows the overflow condition as the rear is pointing
to the last element of the Queue.
Circular Queue
In Circular Queue, all the nodes are represented as circular. It is similar to the
linear Queue except that the last element of the queue is connected to the first
element. It is also known as Ring Buffer, as all the ends are connected to
another end. The representation of circular queue is shown in the below image -
The drawback that occurs in a linear queue is overcome by using the circular
queue. If the empty space is available in a circular queue, the new element can
be added in an empty space by simply incrementing the value of rear. The main
advantage of using the circular queue is better memory utilization.
Priority Queue
It is a special type of queue in which the elements are arranged based on the
priority. It is a special type of queue data structure in which every element has a
priority associated with it. Suppose some elements occur with the same priority,
they will be arranged according to the FIFO principle. The representation of
priority queue is shown in the below image -
Insertion in priority queue takes place based on the arrival, while deletion in the
priority queue occurs based on the priority. Priority queue is mainly used to
implement the CPU scheduling algorithms.
There are two types of priority queue that are discussed as follows
56
Ascending priority queue - In ascending priority queue, elements can be
inserted in arbitrary order, but only smallest can be deleted first. Suppose an
array with elements 7, 5, and 3 in the same order, so, insertion can be done with
the same sequence, but the order of deleting the elements is 3, 5, 7.
Descending priority queue - In descending priority queue, elements can be
inserted in arbitrary order, but only the largest element can be deleted first.
Suppose an array with elements 7, 3, and 5 in the same order, so, insertion can
be done with the same sequence, but the order of deleting the elements is 7, 5, 3.
Deque can be used both as stack and queue as it allows the insertion and
deletion operations on both ends. Deque can be considered as stack because
stack follows the LIFO (Last In First Out) principle in which insertion and
deletion both can be performed only from one end. And in deque, it is possible
to perform both insertion and deletion from one end, and Deque does not follow
the FIFO principle.
Enqueue: The Enqueue operation is used to insert the element at the rear
end of the queue. It returns void.
Dequeue: It performs the deletion from the front-end of the queue. It also
returns the element which has been removed from the front-end. It returns
an integer value.
Peek: This is the third operation that returns the element, which is pointed
by the front pointer in the queue but does not delete it.
Queue overflow (isfull): It shows the overflow condition when the queue
is completely full.
Queue underflow (isempty): It shows the underflow condition when the
Queue is empty, i.e., no elements are in the Queue.
57
We read the linear data structures like an array, linked list, stack and queue in
which all the elements are arranged in a sequential manner. The different data
structures are used for different kinds of data.
A tree is also one of the data structures that represent hierarchical data.
In the above structure, each node is labeled with some number. Each arrow
shown in the above figure is known as a link between the two nodes.
Root: The root node is the topmost node in the tree hierarchy. In other
words, the root node is the one that doesn’t have any parent. In the above
structure, node numbered 1 is the root node of the tree. If a node is
directly linked to some other node, it would be called a parent-child
relationship.
Child node: If the node is a descendant of any node, then the node is
known as a child node.
Parent: If the node contains any sub-node, then that node is said to be the
parent of that sub-node.
Sibling: The nodes that have the same parent are known as siblings.
Leaf Node:- The node of the tree, which doesn’t have any child node, is
called a leaf node. A leaf node is the bottom-most node of the tree. There
can be any number of leaf nodes present in a general tree. Leaf nodes can
also be called external nodes.
Internal nodes: A node has at least one child node known as an internal
58
Ancestor node:- An ancestor of a node is any predecessor node on a path
from the root to that node. The root node doesn’t have any ancestors. In
the tree shown in the above image, nodes 1, 2, and 5 are the ancestors of
node 10.
Descendant: The immediate successor of the given node is known as a
descendant of a node. In the above figure, 10 is the descendant of node 5.
Implementation:
59
}
// Traverse Postorder
void traversePostOrder(struct node *temp) {
if (temp != NULL) {
traversePostOrder(temp->left);
traversePostOrder(temp->right);
cout << " " << temp->data;
}
}
int main() {
struct node *root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
cout << "preorder traversal: ";
traversePreOrder(root);
cout << "\nInorder traversal: ";
traverseInOrder(root);
cout << "\nPostorder traversal: ";
traversePostOrder(root);
Implementation
60
return temp;
}
// Inorder Traversal
void inorder(struct node *root) {
if (root != NULL) {
// Traverse left
inorder(root->left);
// Traverse root
cout << root->key << " -> ";
// Traverse right
inorder(root->right);
}
}
// Insert a node
struct node *insert(struct node *node, int key) {
// Return a new node if the tree is empty
if (node == NULL) return newNode(key);
// Traverse to the right place and insert the node
if (key < node->key)
node->left = insert(node->left, key);
else
node->right = insert(node->right, key);
return node;
}
// Find the inorder successor
struct node *minValueNode(struct node *node) {
struct node *current = node;
// Find the leftmost leaf
while (current && current->left != NULL)
current = current->left;
return current;
}
// Deleting a node
struct node *deleteNode(struct node *root, int key) {
// Return if the tree is empty
if (root == NULL) return root;
// Find the node to be deleted
if (key < root->key)
root->left = deleteNode(root->left, key);
else if (key > root->key)
root->right = deleteNode(root->right, key);
else {
// If the node is with only one child or no child
61
if (root->left == NULL) {
struct node *temp = root->right;
free(root);
return temp;
} else if (root->right == NULL) {
struct node *temp = root->left;
free(root);
return temp;
}
// If the node has two children
struct node *temp = minValueNode(root->right);
// Place the inorder successor in position of the node to be deleted
root->key = temp->key;
// Delete the inorder successor
root->right = deleteNode(root->right, temp->key);
}
return root;
}
// Driver code
int main() {
struct node *root = NULL;
root = insert(root, 8);
root = insert(root, 3);
root = insert(root, 1);
root = insert(root, 6);
root = insert(root, 7);
root = insert(root, 10);
root = insert(root, 14);
root = insert(root, 4);
cout << "Inorder traversal: ";
inorder(root);
cout << "\nAfter deleting 10\n";
root = deleteNode(root, 10);
cout << "Inorder traversal: ";
inorder(root);
}
Graph:
A graph can be defined as a group of vertices and edges that are used to connect
these vertices. A graph can be seen as a cyclic tree, where the vertices (Nodes)
62
maintain any complex relationship among them instead of having parent-child
relationship.
In a directed graph, edges form an ordered pair. Edges represent a specific path
from some vertex A to another vertex B. Node A is called the initial node while
node B is called terminal node.
A directed graph is shown in the following figure.
Adjacency Matrix
Implementation:
#include<iostream>
using namespace std;
int vertArr[20][20]; //the adjacency matrix initially 0
int count = 0;
void displayMatrix(int v) {
int i, j;
for(i = 0; i < v; i++) {
for(j = 0; j < v; j++) {
cout << vertArr[i][j] << " ";
}
cout << endl;
}
}
63
void add_edge(int u, int v) { //function to add edge into the matrix
vertArr[u][v] = 1;
vertArr[v][u] = 1;
}
main(int argc, char* argv[]) {
int v = 6; //there are 6 vertices in the graph
add_edge(0, 4);
add_edge(0, 3);
add_edge(1, 2);
add_edge(1, 4);
add_edge(1, 5);
add_edge(2, 3);
add_edge(2, 5);
add_edge(5, 3);
add_edge(5, 4);
displayMatrix(v);
}
Adjacency List
Implementation:
64
for (auto x : adj[v])
cout << "-> " << x;
printf("\n");
}
}
// Driver code
int main()
{
int V = 5;
vector<int> adj[V];
addEdge(adj, 0, 1);
addEdge(adj, 0, 4);
addEdge(adj, 1, 2);
addEdge(adj, 1, 3);
addEdge(adj, 1, 4);
addEdge(adj, 2, 3);
addEdge(adj, 3, 4);
printGraph(adj, V);
return 0;
}
65
Conclusion
In conclusion, the symbiotic relationship between C++ and Data Structures
emerges as a cornerstone in the field of computer science. The thorough
exploration of C++ fundamentals and diverse data structures provides a robust
foundation for both theoretical understanding and practical application. The
emphasis on algorithmic thinking and problem-solving equips individuals with
essential skills for efficient solution development.
66