Introduction To Data Structures and Algorithms
Introduction To Data Structures and Algorithms
Algorithms
Data Structure is a way of collecting and organising data in such a
way that we can perform operations on these data in an effective
way. Data Structures is about rendering data elements in terms of
some relationship, for better organization and storage. For example,
we have some data which has, player's name "Virat" and age 26.
Here "Virat" is of String data type and 26 is of integer data type.
We can organize this data as a record like Player record, which will
have both player's name and age in it. Now we can collect and store
player's records in a file or database as a data structure. For
example: "Dhoni" 30, "Gambhir" 31, "Sehwag" 33
The data structure is not any programming language like C, C++, java, etc. It is a
set of algorithms that we can use in any programming language to structure the
data in the memory.
The primitive data structures are primitive data types. The int, char, float, double,
and pointer are the primitive data structures that can hold a single value.
We will discuss the above data structures in brief in the coming topics. Now, we will
see the common operations that we can perform on these data structures.
Major Operations
The major or the common operations that can be performed on the data structures
are:
o Updation: We can also update the element, i.e., we can replace the element
with another element.
o Deletion: We can also perform the delete operation to remove the element
from the data structure.
DS Algorithm
What is an Algorithm?
An algorithm is a process or a set of rules required to perform calculations or some
other problem-solving operations especially by a computer. The formal definition of
an algorithm is that it contains the finite set of instructions which are being carried
in a specific order to perform the specific task. It is not the complete program or
code; it is just a solution (logic) of a problem, which can be represented either as an
informal description using a Flowchart or Pseudocode.
Characteristics of an Algorithm
The following are the characteristics of an algorithm:
o Input: An algorithm has some input values. We can pass 0 or some input
value to an algorithm.
o Output: We will get 1 or more output at the end of an algorithm.
Dataflow of an Algorithm
o Problem: A problem can be a real-world problem or any instance from the
real-world problem for which we need to create a program or the set of
instructions. The set of instructions is known as an algorithm.
o Algorithm: An algorithm will be designed for a problem which is a step by
step procedure.
o Input: After designing an algorithm, the required and the desired inputs are
provided to the algorithm.
o Processing unit: The input will be given to the processing unit, and the
processing unit will produce the desired output.
o Output: The output is the outcome or the result of the program.
Step 2: Squeeze the lemon as much you can and take out its juice in a container.
Step 5: When sugar gets dissolved, add some water and ice in it.
The above real-world can be directly compared to the definition of the algorithm. We
cannot perform the step 3 before the step 2, we need to follow the specific order to
make lemon juice. An algorithm also says that each and every instruction should be
followed in a specific order to perform a specific task.
The following are the steps required to add two numbers entered by the
user:
Step 1: Start
Step 4: Add the values of a and b and store the result in the sum variable, i.e.,
sum=a+b.
Step 6: Stop
Approaches of Algorithm
The following are the approaches used after considering both the
theoretical and practical importance of designing an algorithm:
o Brute force algorithm: The general logic structure is applied to design an
algorithm. It is also known as an exhaustive search algorithm that searches
all the possibilities to provide the required solution. Such algorithms are of
two types:
1. Optimizing: Finding all the solutions of a problem and then take out
the best solution or if the value of the best solution is known then it
will terminate if the best solution is known.
2. After breaking down the problem, it finds the optimal solution out of
these subproblems.
Array
Definition
o Arrays are defined as the collection of similar type of data items stored at
contiguous memory locations.
o Arrays are the derived data type in C programming language which can store
the primitive type of data such as int, char, double, float, etc.
o Array is the simplest data structure where each data element can be
randomly accessed by using its index number.
o For example, if we want to store the marks of a student in 6 subjects, then
we don't need to define different variable for the marks in different subject.
instead of that, we can define an array which can store the marks in each
subject at a the contiguous memory locations.
The array marks[10] defines the marks of the student in 10 different subjects
where each subject marks are located at a particular subscript in the array
i.e. marks[0] denotes the marks in first subject, marks[1] denotes the marks in
2nd subject and so on.
2. Elements of the array are stored at contiguous memory locations where the
first element is stored at the smallest memory location.
3. Elements of the array can be randomly accessed since we can calculate the
address of each element of the array with the given base address and the size
of data element.
1. #include <stdio.h>
2. void main ()
3. {
4. int marks[6] = {56,78,88,76,56,89);
5. int i;
6. float avg;
7. for (i=0; i<6; i++ )
8. {
9. avg = avg + marks[i];
10. }
11. printf(avg);
12.}
Advantages of Array
o Array provides the single name for the group of variables of the same type
therefore, it is easy to remember the name of all the elements of an array.
o Traversing an array is a very simple process, we just need to increment the
base address of the array in order to visit each element one by one.
o Any element in the array can be directly accessed by using the index.
1. 0 (zero - based indexing) : The first element of the array will be arr[0].
2. 1 (one - based indexing) : The first element of the array will be arr[1].
3. n (n - based indexing) : The first element of the array can reside at any
random index number.
Pointer
Pointer is used to points the address of the value stored anywhere in the computer
memory. To obtain the value stored at the location is known as dereferencing the
pointer. Pointer improves the performance for repetitive process such as:
o Traversing String
o Lookup Tables
o Control Tables
o Tree Structures
Pointer Details
o Pointer arithmetic: There are four arithmetic operators that can be used in
pointers: ++, --, +, -
o Array of pointers: You can define arrays to hold a number of pointers.
2. value of a = 5
3. address of a = 3010494292
4. address of a = -1284473004
5. address of b = 3010494296
Program
Pointer to Pointer
1. #include <stdio.h>
2.
3. int main( )
4. {
5. int a = 5;
6. int *b;
7. int **c;
8. b = &a;
9. c = &b;
10.printf ("value of a = %d\n", a);
11.printf ("value of a = %d\n", *(&a));
12.printf ("value of a = %d\n", *b);
13.printf ("value of a = %d\n", **c);
14.printf ("value of b = address of a = %u\n", b);
15.printf ("value of c = address of b = %u\n", c);
16.printf ("address of a = %u\n", &a);
17.printf ("address of a = %u\n", b);
18.printf ("address of a = %u\n", *c);
19.printf ("address of b = %u\n", &b);
20.printf ("address of b = %u\n", c);
21.printf ("address of c = %u\n", &c);
22.return 0;
23.}
Pointer to Pointer
1. value of a = 5
2. value of a = 5
3. value of a = 5
4. value of a = 5
9. address of a = 2831685116
10.address of b = 2831685120
11.address of b = 2831685120
12.address of c = 2831685128
Structure
A structure is a composite data type that defines a grouped list of variables that are
to be placed under one name in a block of memory. It allows different variables to
be accessed by using a single pointer to the structure.
Syntax
1. struct structure_name
2. {
3. data_type member1;
4. data_type member2;
5. .
6. .
7. data_type memeber;
8. };
Advantages
o It can hold variables of different data types.
o It is used to implement other data structures like linked lists, stacks, queues,
trees, graphs etc.
o #include<stdio.h>
o #include<conio.h>
o void main( )
o {
o struct employee
o {
o int id ;
o float salary ;
o int mobile ;
o };
o struct employee e1,e2,e3 ;
o clrscr();
o printf ("\nEnter ids, salary & mobile no. of 3 employee\n"
o scanf ("%d %f %d", &e1.id, &e1.salary, &e1.mobile);
o scanf ("%d%f %d", &e2.id, &e2.salary, &e2.mobile);
o scanf ("%d %f %d", &e3.id, &e3.salary, &e3.mobile);
o printf ("\n Entered Result ");
o printf ("\n%d %f %d", e1.id, e1.salary, e1.mobile);
o printf ("\n%d%f %d", e2.id, e2.salary, e2.mobile);
o printf ("\n%d %f %d", e3.id, e3.salary, e3.mobile);
o getch();
o }
Linked List
Before understanding the linked list concept, we first look at why there is a need
for a linked list.
1. int x;
In the above example, we have created a variable 'x' of type integer. As we know
that integer variable occupies 4 bytes, so 'x' variable will occupy 4 bytes to store the
value.
1. int x[3];
In the above example, we have declared an array of size 3. As we know, that all the
values of an array are stored in a continuous manner, so all the three values of an
array are stored in a sequential fashion. The total memory space occupied by the
array would be 3*4 = 12 bytes.
In array, we are providing the fixed-size at the compile-time, due to which wastage
of memory occurs. The solution to this problem is to use the linked list.
Suppose a programmer made a request for storing the integer value then size of 4-
byte memory block is assigned to the integer value. The programmer made another
request for storing 3 more integer elements; then, three different memory blocks
are assigned to these three elements but the memory blocks are available in a
random location. So, how are the elements connected?.
These elements are linked to each other by providing one additional information
along with an element, i.e., the address of the next element. The variable that
stores the address of the next element is known as a pointer. Therefore, we
conclude that the linked list contains two parts, i.e., the first one is the data
element, and the other is the pointer. The pointer variable will occupy 4 bytes
which is pointing to the next element.
A linked list can also be defined as the collection of the nodes in which one
node is connected to another node, and node consists of two parts, i.e., one
is the data part and the second one is the address part, as shown in the
below figure:
How can we declare the Linked list?
The declaration of an array is very simple as it is of single type. But the linked list
contains two parts, which are of two different types, i.e., one is a simple variable,
and the second one is a pointer variable. We can declare the linked list by using the
user-defined data type known as structure.
1. struct node
2. {
3. int data;
4. struct node *next;
5. }
In the above declaration, we have defined a structure named as a node consisting
of two variables: an integer variable (data), and the other one is the pointer (next),
which contains the address of the next node. Advantages of using a
Linked list over Array
The following are the advantages of using a linked list over an array:
o Memory usage
The node in a linked list occupies more memory than array as each node
occupies two types of variables, i.e., one is a simple variable, and another is a
pointer variable that occupies 4 bytes in the memory.
o Traversal
In a linked list, the traversal is not easy. If we want to access the element in
a linked list, we cannot access the element randomly, but in the case of an
array, we can randomly access the element by index. For example, if we want
to access the 3rd node, then we need to traverse all the nodes before it. So,
the time required to access a particular node is large.
o Reverse traversing
In a linked list, backtracking or reverse traversing is difficult. In a doubly
linked list, it is easier but requires more memory to store the back pointer.
Suppose we have three nodes, and the addresses of these three nodes are 100, 200
and 300 respectively. The representation of three nodes as a linked list is shown in
the below figure:
We can observe in the above figure that there are three different nodes having
address 100, 200 and 300 respectively. The first node contains the address of the
next node, i.e., 200, the second node contains the address of the last node, i.e.,
300, and the third node contains the NULL value in its address part as it does not
point to any node. The pointer that holds the address of the initial node is known as
a head pointer.
The linked list, which is shown in the above diagram, is known as a singly linked list
as it contains only a single link. In this list, only forward traversal is possible; we
cannot traverse in the backward direction as it has only one link in the list.
1. struct node
2. {
3. int data;
4. struct node *next;
5. }
To know more about a singly linked list, click on the link given below:
One way chain or singly linked list can be traversed only in one direction. In other
words, we can say that each node contains only next pointer, therefore we can not
traverse the list in the reverse direction.
Consider an example where the marks obtained by the student in three subjects are
stored in a linked list as shown in the figure.
In the above figure, the arrow represents the links. The data part of every node
contains the marks obtained by the student in the different subject. The last node in
the list is identified by the null pointer which is present in the address part of the
last node. We can have as many elements we require, in the data part of the list.