DS Notes
DS Notes
Data is a collection of facts and figures or a set of values or values of a specific format
that refers to a single set of item values. The data items are then classified into sub-
items, which is the group of items that are not known as the simple primary form of the
item.
Let us consider an example where an employee name can be broken down into three
sub-items: First, Middle, and Last. However, an ID assigned to an employee will generally
be considered a single item.
In the example mentioned above, the items such as ID, Age, Gender, First, Middle, Last,
Street, Locality, etc., are elementary data items. In contrast, the Name and the Address
are group data items.
1. Data Structures and Algorithms are two of the key aspects of Computer Science.
2. Data Structures allow us to organize and store data, whereas Algorithms allow us to
process that data meaningfully.
3. Learning Data Structures and Algorithms will help us become better Programmers.
4. We will be able to write code that is more effective and reliable.
5. We will also be able to solve problems more quickly and efficiently.
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.
1. Primitive Data Structures are the data structures consisting of the numbers and
the characters that come in-built into programs.
2. These data structures can be manipulated or operated directly by machine-level
instructions.
3. Basic data types like Integer, Float, Character, and Boolean come under the
Primitive Data Structures.
1. Static Data Structures: The data structures having a fixed size are known as
Static Data Structures. The memory for these data structures is allocated at the
compiler time, and their size cannot be changed by the user after being
compiled; however, the data stored in them can be altered.
The Array is the best example of the Static Data Structure as they have a fixed
size, and its data can be modified later.
2. Dynamic Data Structures: The data structures having a dynamic size are known
as Dynamic Data Structures. The memory of these data structures is allocated at
the run time, and their size varies during the run time of the code. Moreover, the
user can change the size as well as the data elements stored in these data
structures at the run time of the code.
Linked Lists, Stacks, and Queues are common examples of dynamic data
structures
Non-Linear Data Structures are data structures where the data elements are not arranged in
sequential order. Here, the insertion and removal of data are not feasible in a linear manner.
There exists a hierarchical relationship between the individual data items
1. Traversal: Traversing a data structure means accessing each data element exactly once
so it can be administered. For example, traversing is required while printing the names of
all the employees in a department.
2. Search: Search is another data structure operation which means to find the location of
one or more data elements that meet certain constraints. Such a data element may or
may not be present in the given set of data elements. For example, we can use the
search operation to find the names of all the employees who have the experience of
more than 5 years.
3. Insertion: Insertion means inserting or adding new data elements to the collection. For
example, we can use the insertion operation to add the details of a new employee the
company has recently hired.
4. Deletion: Deletion means to remove or delete a specific data element from the given list
of data elements. For example, we can use the deleting operation to delete the name of
an employee who has left the job.
5. Sorting: Sorting means to arrange the data elements in either Ascending or Descending
order depending on the type of application. For example, we can use the sorting
operation to arrange the names of employees in a department in alphabetical order or
estimate the top three performers of the month by arranging the performance of the
employees in descending order and extracting the details of the top three.
6. Merge: Merge means to combine data elements of two sorted lists in order to form a
single list of sorted data elements.
7. Create: Create is an operation used to reserve memory for the data elements of the
program. We can perform this operation using a declaration statement. The creation of
data structure can take place either during the following:
a. Compile-time
b. Run-time
For example, the malloc() function is used in C Language to create data
structure.
8. Selection: Selection means selecting a particular data from the available data. We can
select any particular data by specifying conditions inside the loop.
9. Update: The Update operation allows us to update or modify the data in the data
structure. We can also update any particular data by specifying some conditions inside
the loop, like the Selection operation.
10. Splitting: The Splitting operation allows us to divide data into various subparts
decreasing the overall process completion time.
Static Memory
Static memory is memory that is reserved for variables before the program
runs. Allocation of static memory is also known as compile time memory
allocation.
For example, if you create an integer array of 20 students (e.g. for a summer
semester), C will reserve space for 20 elements which is typically 80 bytes of
memory (20 * 4):
Example:
int students[20];
printf("%lu", sizeof(students)); // 80 bytes
But when the semester starts, it turns out that only 12 students are attending.
Then you have wasted the space of 8 unused elements.
Since you are not able to change the size of the array, you are left with
unnecessary reserved memory.
Note that the program will still run, and it is not damaged in any way. But if
your program contains a lot of this kind of code, it may run slower than it
optimally could.
If you want better control of allocated memory, take a look at Dynamic Memory
below.
Dynamic Memory
Dynamic memory is memory that is allocated after the program starts running.
Allocation of dynamic memory can also be referred to as runtime memory
allocation.
Unlike with static memory, you have full control over how much memory is
being used at any time. You can write code to determine how much memory
you need and allocate it.
Dynamic memory does not belong to a variable, it can only be accessed with
pointers.
To allocate dynamic memory, you can use the malloc() or calloc() functions.
It is necessary to include the <stdlib.h> header to use them.
The malloc() and calloc() functions allocate some memory and return a
pointer to its address.
Now let's have a quick look at the methods used for dynamic memory allocation.
malloc() function in C
The malloc() function allocates single block of requested memory.
calloc() function in C
The calloc() function allocates multiple block of requested memory.
Output
Enter elements of array: 3
Enter elements of array: 10
10
10
Sum=30
realloc() function in C
If memory is not sufficient for malloc() or calloc(), you can reallocate the memory by
realloc() function. In short, it changes the memory size.
The realloc() function modifies the allocated memory size to a new size by
the malloc() and calloc() functions.
If enough space doesn't exist in the current block's memory to expand, a new
block is allocated for the total size of the reallocation, then copies the existing
data to the new block and frees the old block
free() function in C
The memory occupied by malloc() or calloc() functions must be released by calling
free() function. Otherwise, it will consume memory until program exit.
Pointers in C
The pointer in C language is a variable which stores the address of another variable.
This variable can be of type int, char, array, function, or any other pointer. The size of
the pointer depends on the architecture. However, in 32-bit architecture the size of a
pointer is 2 byte.
Consider the following example to define a pointer which stores the address of an
integer.
int n = 10;
int* p = &n; // Variable p of type pointer is pointing to the address of the variable n
of type integer.
Declaring a pointer
The pointer in c language can be declared using * (asterisk symbol). It is also known
as indirection pointer used to dereference a pointer.
int *a;//pointer to int
char *c;//pointer to char
Pointer Example
An example of using pointers to print the address and value is given below.
As you can see in the above figure, pointer variable stores the address of number
variable, i.e., fff4. The value of number variable is 50. But the address of pointer
variable p is aaa3.
By the help of * (indirection operator), we can print the value of pointer variable p.
Let's see the pointer example as explained for the above figure.
#include<stdio.h>
int main(){
int number=50;
int *p;
p=&number;
//stores the address of number variable
printf("Address of p variable is %x \n",p);
// p contains the address of the number therefore printing p gives the address of nu
mber.
printf("Value of p variable is %d \n",*p);
// As we know that * is used to dereference a pointer therefore if we print *p, we will
get the value stored at the address contained by p.
return 0;
}
Output
Address of number variable is fff4
Address of p variable is fff4
Value of p variable is 50
Pointer Arithmetic in C
We can perform arithmetic operations on the pointers like addition, subtraction, etc.
However, as we know that pointer contains the address, the result of an arithmetic
operation performed on the pointer will also be a pointer if the other operand is of type
integer. In pointer-from-pointer subtraction, the result will be an integer value.
Following arithmetic operations are possible on the pointer in C language:
ADVERTISEMENT
o Increment
o Decrement
o Addition
o Subtraction
o Comparison
Incrementing Pointer in C
If we increment a pointer by 1, the pointer will start pointing to the immediate next
location. This is somewhat different from the general arithmetic since the value of the
pointer will get increased by the size of the data type to which the pointer is pointing.
We can traverse an array by using the increment operation on a pointer which will keep
pointing to every element of the array, perform some operation on that, and update
itself in a loop.
32-bit
For 32-bit int variable, it will be incremented by 2 bytes.
64-bit
For 64-bit int variable, it will be incremented by 4 bytes.
#include<stdio.h>
int main(){
int number=50;
int *p;//pointer to int
p=&number;//stores the address of number variable
printf("Address of p variable is %u \n",p);
p=p+1;
printf("After increment: Address of p variable is %u \n",p); // in our case, p will get incremented by 4
bytes.
return 0;
}
Decrementing Pointer in C
Like increment, we can decrement a pointer variable. If we decrement a pointer, it will
start pointing to the previous location. The formula of decrementing the pointer is given
below:
32-bit
For 32-bit int variable, it will be decremented by 2 bytes.
64-bit
For 64-bit int variable, it will be decremented by 4 bytes.
#include <stdio.h>
void main(){
int number=50;
int *p;//pointer to int
p=&number;//stores the address of number variable
printf("Address of p variable is %u \n",p);
p=p-1;
printf("After decrement: Address of p variable is %u \n",p); // P will now point to the immidiate previ
ous location.
}
Output
Address of p variable is 3214864300
After decrement: Address of p variable is 3214864296
C Pointer Addition
We can add a value to the pointer variable. The formula of adding value to pointer is
given below:
32-bit
For 32-bit int variable, it will add 2 * number.
64-bit
Let's see the example of adding value to pointer variable on 64-bit architecture.
#include<stdio.h>
int main(){
int number=50;
int *p;//pointer to int
p=&number;//stores the address of number variable
printf("Address of p variable is %u \n",p);
p=p+3; //adding 3 to pointer variable
printf("After adding 3: Address of p variable is %u \n",p);
return 0;
}
Output
Address of p variable is 3214864300
After adding 3: Address of p variable is 3214864312
As you can see, the address of p is 3214864300. But after adding 3 with p variable, it is
3214864312, i.e., 4*3=12 increment. Since we are using 64-bit architecture, it increments
12. But if we were using 32-bit architecture, it was incrementing to 6 only, i.e., 2*3=6. As
integer value occupies 2-byte memory in 32-bit OS.
C Pointer Subtraction
Like pointer addition, we can subtract a value from the pointer variable. Subtracting any
number from a pointer will give an address. The formula of subtracting value from the
pointer variable is given below:
32-bit
For 32-bit int variable, it will subtract 2 * number.
64-bit
For 64-bit int variable, it will subtract 4 * number.
Let's see the example of subtracting value from the pointer variable on 64-bit
architecture.
#include<stdio.h>
int main(){
int number=50;
int *p;//pointer to int
p=&number;//stores the address of number variable
printf("Address of p variable is %u \n",p);
p=p-3; //subtracting 3 from pointer variable
printf("After subtracting 3: Address of p variable is %u \n",p);
return 0;
}
Output
Address of p variable is 3214864300
After subtracting 3: Address of p variable is 3214864288
You can see after subtracting 3 from the pointer variable, it is 12 (4*3) less than the
previous address value.
Address2 - Address1 = (Subtraction of two addresses)/size of data type which pointer points
#include<stdio.h>
void main ()
{
int i = 100;
int *p = &i;
int *temp;
temp = p;
p = p + 3;
printf("Pointer Subtraction: %d - %d = %d",p, temp, p-temp);
}
Output
Pointer Subtraction: 1030585080 - 1030585068 = 3
Advantage of pointer
1) Pointer reduces the code and improves the performance, it is used to retrieving
strings, trees, etc. and used with arrays, structures, and functions.
3) It makes you able to access any memory location in the computer's memory.
Disadvantage of pointer
Uninitialized pointers might cause segmentation fault.
Dynamically allocated block needs to be freed explicitly. Otherwise, it would lead
to memory leak.
Pointers are slower than normal variables.
If pointers are updated with incorrect values, it might lead to memory corruption.
Usage of pointer
There are many applications of pointers in c language.
Pointers in c language are widely used in arrays, functions, and structures. It reduces
the code and improves the performance.