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

UNIT -4 DSA

DSA

Uploaded by

jaisingh2744
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
22 views

UNIT -4 DSA

DSA

Uploaded by

jaisingh2744
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 67

UNIT-4

Subject:-DSA

Selection Sort Algorithm


In selection sort, the smallest value among the unsorted elements of the
array is selected in every pass and inserted to its appropriate position into
the array. It is also the simplest algorithm. It is an in-place comparison
sorting algorithm. In this algorithm, the array is divided into two parts, first is
sorted part, and another one is the unsorted part. Initially, the sorted part of
the array is empty, and unsorted part is the given array. Sorted part is
placed at the left, while the unsorted part is placed at the right.

In selection sort, the first smallest element is selected from the unsorted
array and placed at the first position. After that second smallest element is
selected and placed in the second position. The process continues until the
array is entirely sorted.

The average and worst-case complexity of selection sort is O(n2), where n is


the number of items. Due to this, it is not suitable for large data sets.

Selection sort is generally used when -

o A small array is to be sorted


o Swapping cost doesn't matter
o It is compulsory to check all elements
Algorithm for Selection Sort:
This algorithm sorts array a of n elements a[0] to a[n-1]

Step 1 – Repeat step 2,3,4,5, for pass = 0 to n-1.

Step 2 – set smallest a [pass]

Step 3 – set loc pass

Step 4 – for j = (pass +1) to (n-1) repeat step (a)

(a) If a [j] < smallest then

(i) set smallest a [j]

(ii) set loc j

Step 5 – (i) set temp a[pass]

(ii) set a[pass] a[loc]

(iii) set a[loc] temp

Step 6 – Exit

Working of Selection sort Algorithm


Now, let's see the working of the Selection sort Algorithm.

To understand the working of the Selection sort algorithm, let's take an unsorted array. It will be
easier to understand the Selection sort via an example.
Selection sort complexity
Now, let's see the time complexity of selection sort in best case, average
case, and in worst case. We will also see the space complexity of the
selection sort.

. Time Complexity
Case Time Complexity

Best Case O(n2)

Average Case O(n2)

Worst Case O(n2)

o Best Case Complexity - It occurs when there is no sorting required, i.e. the
array is already sorted. The best-case time complexity of selection sort
is O(n2).
o Average Case Complexity - It occurs when the array elements are in
jumbled order that is not properly ascending and not properly descending.
The average case time complexity of selection sort is O(n2).
o Worst Case Complexity - It occurs when the array elements are required to
be sorted in reverse order. That means suppose you have to sort the array
elements in ascending order, but its elements are in descending order. The
worst-case time complexity of selection sort is O(n2).
o

2. Space Complexity

Space Complexity O(1)

Stable YES

o The space complexity of selection sort is O(1). It is because, in selection sort,


an extra variable is required for swapping.
Bubble sort Algorithm
The working procedure of bubble sort is simplest.

Bubble sort works on the repeatedly swapping of adjacent elements until


they are not in the intended order. It is called bubble sort because the
movement of array elements is just like the movement of air bubbles in the
water. Bubbles in water rise up to the surface; similarly, the array elements
in bubble sort move to the end in each iteration.

Although it is simple to use, it is primarily used as an educational tool


because the performance of bubble sort is poor in the real world. It is not
suitable for large data sets. The average and worst-case complexity of
Bubble sort is O(n2), where n is a number of items.

Bubble short is majorly used where -

o complexity does not matter


o simple and short code is preferred

Algorithm for Bubble Sort:


Let the array A consists of n elements

Step 1 – Repeat step 2 for pass = 1 to n-1.

Step 2 – For j = 1 to (n-pass) repeat step 3.

Step 3 – set loc pass

Step 4 – if a [j] > a [j+1] then

(i) set temp a[j]

(ii) set a[j] a [ j+1]

(iii) set a [ j+1] temp

Step 5 – Exit.

Example:- sort the array 32,13,64,1,55,48,84,26,89,77 in ascending order---


Bubble sort complexity
Now, let's see the time complexity of bubble sort in the best case, average
case, and worst case. We will also see the space complexity of bubble sort.

1. Time Complexity
Case Time Complexity

Best Case O(n)

Average Case O(n2)

Worst Case O(n2)

o Best Case Complexity - It occurs when there is no sorting required, i.e. the
array is already sorted. The best-case time complexity of bubble sort is O(n).
o Average Case Complexity - It occurs when the array elements are in
jumbled order that is not properly ascending and not properly descending.
The average case time complexity of bubble sort is O(n2).
o Worst Case Complexity - It occurs when the array elements are required to
be sorted in reverse order. That means suppose you have to sort the array
elements in ascending order, but its elements are in descending order. The
worst-case time complexity of bubble sort is O(n2).

2. Space Complexity
Space Complexity O(1)

Stable YES

o The space complexity of bubble sort is O(1). It is because, in bubble sort, an


extra variable is required for swapping.
o The space complexity of optimized bubble sort is O(2). It is because two extra
variables are required in optimized bubble sort.

Insertion Sort Algorithm


Insertion sort works similar to the sorting of playing cards in hands. It is
assumed that the first card is already sorted in the card game, and then we
select an unsorted card. If the selected unsorted card is greater than the first
card, it will be placed at the right side; otherwise, it will be placed at the left
side. Similarly, all unsorted cards are taken and put in their exact place.

The same approach is applied in insertion sort. The idea behind the insertion
sort is that first take one element, iterate it through the sorted array.
Although it is simple to use, it is not appropriate for large data sets as the
time complexity of insertion sort in the average case and worst case
is O(n2), where n is the number of items. Insertion sort is less efficient than
the other sorting algorithms like heap sort, quick sort, merge sort, etc.

Insertion sort has various advantages such as -

o Simple implementation
o Efficient for small data sets
o Adaptive, i.e., it is appropriate for data sets that are already
substantially sorted.

Now, let's see the algorithm of insertion sort.

Algorithm
The simple steps of achieving the insertion sort are listed as follows -

Step 1 - If the element is the first element, assume that it is already sorted.
Return 1.

Step2 - Pick the next element, and store it separately in a key.

Step3 - Now, compare the key with all elements in the sorted array.

Step 4 - If the element in the sorted array is smaller than the current
element, then move to the next element. Else, shift greater elements in the
array towards the right.

Step 5 - Insert the value.

Step 6 - Repeat until the array is sorted.


Example of Insertion sort:-

This process is repeated till all the elements of the parts


are executed.

Insertion sort complexity


Now, let's see the time complexity of insertion sort in best case, average
case, and in worst case. We will also see the space complexity of insertion
sort.

1. Time Complexity
Case Time Complexity

Best Case O(n)


Average Case O(n2)

Worst Case O(n2)

o Best Case Complexity - It occurs when there is no sorting required, i.e. the
array is already sorted. The best-case time complexity of insertion sort
is O(n).
o Average Case Complexity - It occurs when the array elements are in
jumbled order that is not properly ascending and not properly descending.
The average case time complexity of insertion sort is O(n2).
o Worst Case Complexity - It occurs when the array elements are required to
be sorted in reverse order. That means suppose you have to sort the array
elements in ascending order, but its elements are in descending order. The
worst-case time complexity of insertion sort is O(n2).

2. Space Complexity
Space Complexity O(1)

Stable YES

o The space complexity of insertion sort is O(1). It is because, in insertion sort,


an extra variable is required for swapping.

Quick Sort Algorithm


Sorting is a way of arranging items in a systematic manner. Quicksort is the
widely used sorting algorithm that makes n log n comparisons in average
case for sorting an array of n elements. It is a faster and highly efficient
sorting algorithm. This algorithm follows the divide and conquer approach.
Divide and conquer is a technique of breaking down the algorithms into
subproblems, then solving the subproblems, and combining the results back
together to solve the original problem.

Divide: In Divide, first pick a pivot element. After that, partition or rearrange
the array into two sub-arrays such that each element in the left sub-array is
less than or equal to the pivot element and each element in the right sub-
array is larger than the pivot element.

Conquer: Recursively, sort two subarrays with Quicksort.

Combine: Combine the already sorted array.

Quicksort picks an element as pivot, and then it partitions the given array
around the picked pivot element. In quick sort, a large array is divided into
two arrays in which one holds values that are smaller than the specified
value (Pivot), and another array holds the values that are greater than the
pivot.

After that, left and right sub-arrays are also partitioned using the same
approach. It will continue until the single element remains in the sub-array.

Choosing the pivot


Picking a good pivot is necessary for the fast implementation of quicksort.
However, it is typical to determine a good pivot. Some of the ways of
choosing a pivot are as follows -

o Pivot can be random, i.e. select the random pivot from the given array.
o Pivot can either be the rightmost element of the leftmost element of the
given array.
o Select median as the pivot element.
Algorithm
Algorithm:

1. QUICKSORT (array A, start, end)


2. {
3. 1 if (start < end)
4. 2{
5. 3 p = partition(A, start, end)
6. 4 QUICKSORT (A, start, p - 1)
7. 5 QUICKSORT (A, p + 1, end)
8. 6 }
9. }

Partition Algorithm:

The partition algorithm rearranges the sub-arrays in a place.

1. PARTITION (array A, start, end)


2. {
3. 1 pivot ? A[end]
4. 2 i ? start-1
5. 3 for j ? start to end -1 {
6. 4 do if (A[j] < pivot) {
7. 5 then i ? i + 1
8. 6 swap A[i] with A[j]
9. 7 }}
10. 8 swap A[i+1] with A[end]
11. 9 return i+1
12.}

Working of Quick Sort Algorithm


Now, let's see the working of the Quicksort Algorithm.
To understand the working of quick sort, let's take an unsorted array. It will
make the concept more clear and understandable.

Let the elements of array are -

In the given array, we consider the leftmost element as pivot. So, in this
case, a[left] = 24, a[right] = 27 and a[pivot] = 24.

Since, pivot is at left, so algorithm starts from right and move towards left.

Now, a[pivot] < a[right], so algorithm moves forward one position towards
left, i.e. -

Now, a[left] = 24, a[right] = 19, and a[pivot] = 24.


Because, a[pivot] > a[right], so, algorithm will swap a[pivot] with a[right],
and pivot moves to right, as -

Now, a[left] = 19, a[right] = 24, and a[pivot] = 24. Since, pivot is at right, so
algorithm starts from left and moves to right.

As a[pivot] > a[left], so algorithm moves one position to right as -

Now, a[left] = 9, a[right] = 24, and a[pivot] = 24. As a[pivot] > a[left], so algorithm moves one
position to right as -
Now, a[left] = 29, a[right] = 24, and a[pivot] = 24. As a[pivot] < a[left], so, swap a[pivot] and
a[left], now pivot is at left, i.e. -

Since, pivot is at left, so algorithm starts from right, and move to left. Now, a[left] = 24, a[right]
= 29, and a[pivot] = 24. As a[pivot] < a[right], so algorithm moves one position to left, as -

Now, a[pivot] = 24, a[left] = 24, and a[right] = 14. As a[pivot] > a[right], so, swap a[pivot] and
a[right], now pivot is at right, i.e. -
Now, a[pivot] = 24, a[left] = 14, and a[right] = 24. Pivot is at right, so the algorithm starts from
left and move to right.

Now, a[pivot] = 24, a[left] = 24, and a[right] = 24. So, pivot, left and right are pointing the same
element. It represents the termination of procedure.

Element 24, which is the pivot element is placed at its exact position.

Elements that are right side of element 24 are greater than it, and the
elements that are left side of element 24 are smaller than it.
Now, in a similar manner, quick sort algorithm is separately applied to the
left and right sub-arrays. After sorting gets done, the array will be -

Quicksort complexity
Now, let's see the time complexity of quicksort in best case, average case,
and in worst case. We will also see the space complexity of quicksort.

1. Time Complexity
Case Time Complexity

Best Case O(n*logn)

Average Case O(n*logn)

Worst Case O(n2)

o Best Case Complexity - In Quicksort, the best-case occurs when the pivot
element is the middle element or near to the middle element. The best-case
time complexity of quicksort is O(n*logn).
o Average Case Complexity - It occurs when the array elements are in
jumbled order that is not properly ascending and not properly descending.
The average case time complexity of quicksort is O(n*logn).
o Worst Case Complexity - In quick sort, worst case occurs when the pivot
element is either greatest or smallest element. Suppose, if the pivot element
is always the last element of the array, the worst case would occur when the
given array is sorted already in ascending or descending order. The worst-
case time complexity of quicksort is O(n2).

Though the worst-case complexity of quicksort is more than other sorting


algorithms such as Merge sort and Heap sort, still it is faster in practice.
Worst case in quick sort rarely occurs because by changing the choice of
pivot, it can be implemented in different ways. Worst case in quicksort can
be avoided by choosing the right pivot element.

2. Space Complexity
Space Complexity O(n*logn)

Stable NO

o The space complexity of quicksort is O(n*log n).

Heap Sort Algorithm


Heap sort processes the elements by creating the min-heap or max-heap
using the elements of the given array. Min-heap or max-heap represents the
ordering of array in which the root element represents the minimum or
maximum element of the array.

Heap sort basically recursively performs two main operations -

o Build a heap H, using the elements of array.


o Repeatedly delete the root element of the heap formed in 1 st phase.

Before knowing more about the heap sort, let's first see a brief description
of Heap.

What is a heap?
A heap is a complete binary tree, and the binary tree is a tree in which the
node can have the utmost two children. A complete binary tree is a binary
tree in which all the levels except the last level, i.e., leaf node, should be
completely filled, and all the nodes should be left-justified.

What is heap sort?


Heapsort is a popular and efficient sorting algorithm. The concept of heap
sort is to eliminate the elements one by one from the heap part of the list,
and then insert them into the sorted part of the list.
Heapsort is the in-place sorting algorithm.

Now, let's see the algorithm of heap sort.

Algorithm
1. HeapSort(arr)
2. BuildMaxHeap(arr)
3. for i = length(arr) to 2
4. swap arr[1] with arr[i]
5. heap_size[arr] = heap_size[arr] ? 1
6. MaxHeapify(arr,1)
7. End

BuildMaxHeap(arr)

1. BuildMaxHeap(arr)
2. heap_size(arr) = length(arr)
3. for i = length(arr)/2 to 1
4. MaxHeapify(arr,i)
5. End

MaxHeapify(arr,i)

1. MaxHeapify(arr,i)
2. L = left(i)
3. R = right(i)
4. if L ? heap_size[arr] and arr[L] > arr[i]
5. largest = L
6. else
7. largest = i
8. if R ? heap_size[arr] and arr[R] > arr[largest]
9. largest = R
10.if largest != i
11.swap arr[i] with arr[largest]
12.MaxHeapify(arr,largest)
13.End
Working of Heap sort Algorithm
Now, let's see the working of the Heap sort Algorithm.

In heap sort, basically, there are two phases involved in the sorting of
elements. By using the heap sort algorithm, they are as follows -

o The first step includes the creation of a heap by adjusting the elements of the
array.
o After the creation of heap, now remove the root element of the heap
repeatedly by shifting it to the end of the array, and then store the heap
structure with the remaining elements.

Now let's see the working of heap sort in detail by using an example. To
understand it more clearly, let's take an unsorted array and try to sort it
using heap sort. It will make the explanation clearer and easier.

First, we have to construct a heap from the given array and convert it into
max heap.

After converting the given heap into max heap, the array elements are -
Next, we have to delete the root element (89) from the max heap. To delete
this node, we have to swap it with the last node, i.e. (11). After deleting the
root element, we again have to heapify it to convert it into max heap.

After swapping the array element 89 with 11, and converting the heap into
max-heap, the elements of array are -

In the next step, again, we have to delete the root element (81) from the
max heap. To delete this node, we have to swap it with the last node,
i.e. (54). After deleting the root element, we again have to heapify it to
convert it into max heap.
After swapping the array element 81 with 54 and converting the heap into
max-heap, the elements of array are -

In the next step, we have to delete the root element (76) from the max heap
again. To delete this node, we have to swap it with the last node,
i.e. (9). After deleting the root element, we again have to heapify it to
convert it into max heap.

After swapping the array element 76 with 9 and converting the heap into
max-heap, the elements of array are -

In the next step, again we have to delete the root element (54) from the
max heap. To delete this node, we have to swap it with the last node,
i.e. (14). After deleting the root element, we again have to heapify it to
convert it into max heap.
After swapping the array element 54 with 14 and converting the heap into
max-heap, the elements of array are -

In the next step, again we have to delete the root element (22) from the
max heap. To delete this node, we have to swap it with the last node,
i.e. (11). After deleting the root element, we again have to heapify it to
convert it into max heap.

After swapping the array element 22 with 11 and converting the heap into
max-heap, the elements of array are -

In the next step, again we have to delete the root element (14) from the
max heap. To delete this node, we have to swap it with the last node,
i.e. (9). After deleting the root element, we again have to heapify it to
convert it into max heap.

After swapping the array element 14 with 9 and converting the heap into
max-heap, the elements of array are -

In the next step, again we have to delete the root element (11) from the
max heap. To delete this node, we have to swap it with the last node,
i.e. (9). After deleting the root element, we again have to heapify it to
convert it into max heap.

After swapping the array element 11 with 9, the elements of array are -

Now, heap has only one element left. After deleting it, heap will be empty.
After completion of sorting, the array elements are -

Now, the array is completely sorted.

Heap sort complexity


Now, let's see the time complexity of Heap sort in the best case, average
case, and worst case. We will also see the space complexity of Heapsort.

1. Time Complexity
Case Time Complexity

Best Case O(n logn)

Average Case O(n log n)

Worst Case O(n log n)

o Best Case Complexity - It occurs when there is no sorting required, i.e. the
array is already sorted. The best-case time complexity of heap sort is O(n
logn).
o Average Case Complexity - It occurs when the array elements are in
jumbled order that is not properly ascending and not properly descending.
The average case time complexity of heap sort is O(n log n).
o Worst Case Complexity - It occurs when the array elements are required to
be sorted in reverse order. That means suppose you have to sort the array
elements in ascending order, but its elements are in descending order. The
worst-case time complexity of heap sort is O(n log n).

The time complexity of heap sort is O(n logn) in all three cases (best case,
average case, and worst case). The height of a complete binary tree having n
elements is logn.
2. Space Complexity
Space Complexity O(1)

Stable N0

o The space complexity of Heap sort is O(1).


Merge Sort Algorithm
Merge sort is similar to the quick sort algorithm as it uses the divide and
conquer approach to sort the elements. It is one of the most popular and
efficient sorting algorithm. It divides the given list into two equal halves, calls
itself for the two halves and then merges the two sorted halves. We have to
define the merge() function to perform the merging.

The sub-lists are divided again and again into halves until the list cannot be
divided further. Then we combine the pair of one element lists into two-
element lists, sorting them in the process. The sorted two-element pairs is
merged into the four-element lists, and so on until we get the sorted list.

Now, let's see the algorithm of merge sort.

Algorithm
In the following algorithm, arr is the given array, beg is the starting
element, and end is the last element of the array.

1. MERGE_SORT(arr, beg, end)


2.
3. if beg < end
4. set mid = (beg + end)/2
5. MERGE_SORT(arr, beg, mid)
6. MERGE_SORT(arr, mid + 1, end)
7. MERGE (arr, beg, mid, end)
8. end of if
9.
10.END MERGE_SORT

The important part of the merge sort is the MERGE function. This function
performs the merging of two sorted sub-arrays that are A[beg…
mid] and A[mid+1…end], to build one sorted array A[beg…end]. So, the
inputs of the MERGE function are A[], beg, mid, and end.
Working of Merge sort Algorithm
Now, let's see the working of merge sort Algorithm.

To understand the working of the merge sort algorithm, let's take an unsorted array. It will be
easier to understand the merge sort via an example.

Let the elements of array are -

According to the merge sort, first divide the given array into two equal halves. Merge sort keeps
dividing the list into equal parts until it cannot be further divided.

As there are eight elements in the given array, so it is divided into two arrays
of size 4.

Now, again divide these two arrays into halves. As they are of size 4, so
divide them into new arrays of size 2.

Now, again divide these arrays to get the atomic value that cannot be further
divided.

Now, combine them in the same manner they were broken.


In combining, first compare the element of each array and then combine
them into another array in sorted order.

So, first compare 12 and 31, both are in sorted positions. Then compare 25 and 8, and in the list
of two values, put 8 first followed by 25. Then compare 32 and 17, sort them and put 17 first
followed by 32. After that, compare 40 and 42, and place them sequentially.

In the next iteration of combining, now compare the arrays with two data values and merge them
into an array of found values in sorted order.

Now, there is a final merging of the arrays. After the final merging of above arrays, the array will
look like -

Now, the array is completely sorted.

Merge sort complexity


Now, let's see the time complexity of merge sort in best case, average case,
and in worst case. We will also see the space complexity of the merge sort.

1. Time Complexity
Case Time Complexity

Best Case O(n*logn)


Average Case O(n*logn)

Worst Case O(n*logn)

o Best Case Complexity - It occurs when there is no sorting required, i.e. the
array is already sorted. The best-case time complexity of merge sort
is O(n*logn).
o Average Case Complexity - It occurs when the array elements are in
jumbled order that is not properly ascending and not properly descending.
The average case time complexity of merge sort is O(n*logn).
o Worst Case Complexity - It occurs when the array elements are required to
be sorted in reverse order. That means suppose you have to sort the array
elements in ascending order, but its elements are in descending order. The
worst-case time complexity of merge sort is O(n*logn).

2. Space Complexity
Space Complexity O(n)

Stable YES

o The space complexity of merge sort is O(n). It is because, in merge sort, an


extra variable is required for swapping.

Radix Sort Algorithm


Radix sort is the linear sorting algorithm that is used for integers. In Radix
sort, there is digit by digit sorting is performed that is started from the least
significant digit to the most significant digit.

The process of radix sort works similar to the sorting of students names,
according to the alphabetical order. In this case, there are 26 radix formed
due to the 26 alphabets in English. In the first pass, the names of students
are grouped according to the ascending order of the first letter of their
names. After that, in the second pass, their names are grouped according to
the ascending order of the second letter of their name. And the process
continues until we find the sorted list.
Now, let's see the algorithm of Radix sort.

Algorithm
1. radixSort(arr)
2. max = largest element in the given array
3. d = number of digits in the largest element (or, max)
4. Now, create d buckets of size 0 - 9
5. for i -> 0 to d
6. sort the array elements using counting sort (or any stable sort) according to the digi
ts at
7. the ith place

Working of Radix sort Algorithm

Example of Radix Sort Algorithm

Let's assume we have an array a=[682, 244, 73, 6, 535,


123]a=[682,244,73,6,535,123] –
Now we apply counting sort on the second digit of the numbers, after which the
numbers will get sorted on the basis of 2^{nd}2nd least-significant digits -
And it's done, now the array is sorted in ascending order.
Hashing
Hashing is one of the searching techniques that uses a constant time. The
time complexity in hashing is O(1). Till now, we read the two techniques for
searching, i.e., linear search and binary search. The worst time complexity in
linear search is O(n), and O(logn) in binary search. In both the searching
techniques, the searching depends upon the number of elements but we
want the technique that takes a constant time. So, hashing technique came
that provides a constant time.

In Hashing technique, the hash table and hash function are used. Using the
hash function, we can calculate the address at which the value can be
stored.

The main idea behind the hashing is to create the (key/value) pairs. If the
key is given, then the algorithm computes the index at which the value
would be stored. It can be written as:

Index = hash(key)

Types of Hashing functions:-


- Some of the common hashing functions are:-
(a) Division method:-

- In this method, each key is divided by a suitable number so that the quotients can be
used for addressing the records, eg. Suppose the keys are 101, 201, 301, 401, 501 and
let suitable number 100 then the addresses are 1, 2, 3, 4, 5 respectively.

(b) Division/Remainder method:-

- In this method, the keys are divided by a suitable number and the remainder is used
for addressing the records.

(C.) Prime division method:-


- This method is an extension of division/remainder method.

In this method, the possibility of number of collisions is quite low.

A prime number closer to the number of records is selected as divisor.


e.g. Consider a file with 20 records. Taking 100 as divisor and the key values of the
addresses as 550, 650, 750, the remainder will be 50, 50, 50 respectively. To overcome
this, we select a prime number closer to the number of records say 19, then the
remainder would be 18, 4, 9 respectively.

(d) Mid square method:-

In this method

Square the key value of the record.

Extract a suitable number of digits from the middle of the squared value to get the
address of the record on the disk.

e.g. Let there be a file with 80 records then 2 digits address is required. Let the key
value of the record be 583, then square of 583-339889. Now drop the first two and last
two digits of this number. We get 98. So physical address of the location of the record
will be 98 which is the middle digits of the square of the key value.

(e) Truncation method:-

- Truncation method is also a division method which uses powers of 10 for division.
Suppose a digits key field is to be converted into 4 digit addresses, then the rightmost 4
digits of the keys can be used as addresses.

Thus if the key-field is 234658329, then the address of the key is 8329.
Truncation gives desirable results if the keys are continuous.

(f) Extraction method:-

In this method any suitable group of digits can be extracted from the key-field.

- Let the given key value be 987654321, the three digit address can be extracted from
the middle to give address as 654. The extraction need not be a continuous string of
digits. The address can be formed by extracting the second, fourth and seventh digit,
giving the address as 863. Extraction is better than truncation method.

(g) Folding method:-

- In this method the key is split into pieces and suitable arithmetic operations are done
on the pieces.

e.g.

(i) Folding:-

Key: 285652

Extraction & addition: 285+ 652

Address: 937

(ii) Folding with remainder/division:-

Key: 198765432

Extraction & addition: 198 + 765 + 432

Sum: 1395 (Divide it by 1000)

Address: 395 (Remainder)

(iii) Boundary folding with remainder/division:-

In this method reverse the digits from the left half of the key before addition, which is
known as boundary folding.

Key : 289649

Leftmost 3 digits: 289


Reverse number: 982

Addition: 982+649 1631

Address 631.

Collision-handling techniques:-

- There are two types of such techniques:-

(a) Open addressing.

(b) Chaining.

(a) Open addressing:-

In open addressing if the address location to which the key is hashed is free, the
element is stored at that location.

In case it is already filled, then other address locations are examined systematically to
find a free address location.

- If no such address location is found then overflow condition occurs.

The process of examining the address locations is called probing.

Open addressing collision handling methods are:-

(i) Linear probing


(ii) Quadratic probing.
(iii) Double hashing.
Graph
A graph can be defined as 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) maintain any complex relationship
among them instead of having parent child relationship.

Definition
A graph G can be defined as an ordered set G(V, E) where V(G) represents the set of vertices
and E(G) represents the set of edges which are used to connect these vertices.

A Graph G(V, E) with 5 vertices (A, B, C, D, E) and six edges ((A,B), (B,C), (C,E), (E,D),
(D,B), (D,A)) is shown in the following figure.

Directed and Undirected Graph


A graph can be directed or undirected. However, in an undirected graph, edges are not associated
with the directions with them. An undirected graph is shown in the above figure since its edges
are not attached with any of the directions. If an edge exists between vertex A and B then the
vertices can be traversed from B to A as well as A to B.

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 initial node
while node B is called terminal node.

A directed graph is shown in the following figure.


Graph Terminology
Path
A path can be defined as the sequence of nodes that are followed in order to
reach some terminal node V from the initial node U.

Closed Path
A path will be called as closed path if the initial node is same as terminal
node. A path will be closed path if V0=VN.

Simple Path
If all the nodes of the graph are distinct with an exception V 0=VN, then such
path P is called as closed simple path.

Cycle
A cycle can be defined as the path which has no repeated edges or vertices
except the first and last vertices.

Connected Graph
A connected graph is the one in which some path exists between every two
vertices (u, v) in V. There are no isolated nodes in connected graph.
Complete Graph
A complete graph is the one in which every node is connected with all other
nodes. A complete graph contain n(n-1)/2 edges where n is the number of
nodes in the graph.

Weighted Graph
In a weighted graph, each edge is assigned with some data such as length or
weight. The weight of an edge e can be given as w(e) which must be a
positive (+) value indicating the cost of traversing the edge.

Digraph
A digraph is a directed graph in which each edge of the graph is associated
with some direction and the traversing can be done only in the specified
direction.

Loop
An edge that is associated with the similar end points can be called as Loop.

Adjacent Nodes
If two nodes u and v are connected via an edge e, then the nodes u and v
are called as neighbours or adjacent nodes.

Degree of the Node


A degree of a node is the number of edges that are connected with that
node. A node with degree 0 is called as isolated node.

Types of Graph

1. Undirected graph
An undirected graph (graph) is a graph in which edges have no orientation.
The edge (x, y) is identical to edge (y, x) , i.e., they are not ordered pairs.
The maximum number of edges possible in an undirected graph without a
loop is n×(n-1)/2 .

2. Directed graph
A Directed graph (digraph) is a graph in which edges have orientations, i.e.,
The edge (x, y) is not identical to edge (y, x) .

3. Directed Acyclic Graph (DAG)


A Directed Acyclic Graph (DAG) is a directed graph that contains no cycles.
4. Multi graph
A multigraph is an undirected graph in which multiple edges (and sometimes
loops) are allowed. Multiple edges are two or more edges that connect the
same two vertices. A loop is an edge (directed or undirected) that connects a
vertex to itself; it may be permitted or not.

5. Simple graph
A simple graph is an undirected graph in which both multiple edges and
loops are disallowed as opposed to a multigraph. In a simple graph
with n vertices, every vertex’s degree is at most n-1 .
6. Weighted and Unweighted graph
A weighted graph associates a value (weight) with every edge in the graph.
We can also use words cost or length instead of weight.

An unweighted graph does not have any value (weight) associated with
every edge in the graph. In other words, an unweighted graph is a weighted
graph with all edge weight as 1. Unless specified otherwise, all graphs are
assumed to be unweighted by default.
7. Complete graph
A complete graph is one in which every two vertices are adjacent: all edges
that could exist are present.

8. Connected graph
A Connected graph has a path between every pair of vertices. In other
words, there are no unreachable vertices. A disconnected graph is a graph
that is not connected.

Graph Representations
In graph theory, a graph representation is a technique to store graph into the
memory of computer.

To represent a graph, we just need the set of vertices, and for each vertex
the neighbors of the vertex (vertices which is directly connected to it by an
edge). If it is a weighted graph, then the weight will be associated with each
edge.

There are different ways to optimally represent a graph, depending on the


density of its edges, type of operations to be performed and ease of use.

1. Adjacency Matrix
o Adjacency matrix is a sequential representation.
o It is used to represent which nodes are adjacent to each other. i.e. is there
any edge connecting nodes to a graph.
o In this representation, we have to construct a nXn matrix A. If there is any
edge from a vertex i to vertex j, then the corresponding element of A, a i,j = 1,
otherwise ai,j= 0.

Note, even if the graph on 100 vertices contains only 1 edge, we still have to have a
100x100 matrix with lots of zeroes.
o If there is any weighted graph then instead of 1s and 0s, we can store the
weight of the edge.

Example
Consider the following undirected graph representation: Undirected
graph representation
Directed graph represenation

See the directed graph representation:

In the above examples, 1 represents an edge from row vertex to column


vertex, and 0 represents no edge from row vertex to column vertex.

Undirected weighted graph represenation


Pros: Representation is easier to implement and follow.

Cons: It takes a lot of space and time to visit all the neighbors of a vertex,
we have to traverse all the vertices in the graph, which takes quite some
time.

Adjacency List
o Adjacency list is a linked representation.
o In this representation, for each vertex in the graph, we maintain the list of its
neighbors. It means, every vertex of the graph contains list of its adjacent
vertices.
o We have an array of vertices which is indexed by the vertex number and for
each vertex v, the corresponding array element points to a singly linked
list of neighbors of v.

Example
Let's see the following directed graph representation implemented using
linked list:
We can also implement this representation using array as follows:

Pros:

o Adjacency list saves lot of space.


o We can easily insert or delete as we use linked list.
o Such kind of representation is easy to follow and clearly shows the adjacent
nodes of node.

Cons:

o The adjacency list allows testing whether two vertices are adjacent to
each other but it is slower to support this operation.
Graph Traversal - BFS
Graph traversal is a technique used for searching a vertex in a graph. The graph traversal is also

used to decide the order of vertices is visited in the search process. A graph traversal finds the

edges to be used in the search process without creating loops. That means using graph traversal we

visit all the vertices of the graph without getting into looping path.

There are two graph traversal techniques and they are as follows...

1. DFS (Depth First Search)

2. BFS (Breadth First Search)

BFS (Breadth First Search)

BFS traversal of a graph produces a spanning tree as final result. Spanning Tree is a graph

without loops. We use Queue data structure with maximum size of total number of vertices in the

graph to implement BFS traversal.

We use the following steps to implement BFS traversal...

 Step 1 - Define a Queue of size total number of vertices in the graph.

 Step 2 - Select any vertex as starting point for traversal. Visit that vertex and insert it into

the Queue.

 Step 3 - Visit all the non-visited adjacent vertices of the vertex which is at front of the Queue

and insert them into the Queue.

 Step 4 - When there is no new vertex to be visited from the vertex which is at front of the

Queue then delete that vertex.

 Step 5 - Repeat steps 3 and 4 until queue becomes empty.


 Step 6 - When queue becomes empty, then produce final spanning tree by removing unused

edges from the graph

 Example
DFS (Depth First Search) algorithm
In this article, we will discuss the DFS algorithm in the data structure. It is a
recursive algorithm to search all the vertices of a tree data structure or a
graph. The depth-first search (DFS) algorithm starts with the initial node of
graph G and goes deeper until we find the goal node or the node with no
children.

Because of the recursive nature, stack data structure can be used to


implement the DFS algorithm. The process of implementing the DFS is
similar to the BFS algorithm.

The step by step process to implement the DFS traversal is given as follows -

1. First, create a stack with the total number of vertices in the graph.
2. Now, choose any vertex as the starting point of traversal, and push that
vertex into the stack.
3. After that, push a non-visited vertex (adjacent to the vertex on the top of the
stack) to the top of the stack.
4. Now, repeat steps 3 and 4 until no vertices are left to visit from the vertex on
the stack's top.
5. If no vertex is left, go back and pop a vertex from the stack.
6. Repeat steps 2, 3, and 4 until the stack is empty.

Applications of DFS algorithm


The applications of using the DFS algorithm are given as follows -

o DFS algorithm can be used to implement the topological sorting.


o It can be used to find the paths between two vertices.
o It can also be used to detect cycles in the graph.
o DFS algorithm is also used for one solution puzzles.
o DFS is used to determine if a graph is bipartite or not.

Algorithm
Step 1: SET STATUS = 1 (ready state) for each node in G

Step 2: Push the starting node A on the stack and set its STATUS = 2
(waiting state)

Step 3: Repeat Steps 4 and 5 until STACK is empty

Step 4: Pop the top node N. Process it and set its STATUS = 3 (processed
state)

Step 5: Push on the stack all the neighbors of N that are in the ready state
(whose STATUS = 1) and set their STATUS = 2 (waiting state)

[END OF LOOP]

Step 6: EXIT

Example of DFS algorithm


Now, let's understand the working of the DFS algorithm by using an example.
In the example given below, there is a directed graph having 7 vertices.
Now, let's start examining the graph starting from Node H.

Step 1 - First, push H onto the stack.

1. STACK: H

Step 2 - POP the top element from the stack, i.e., H, and print it. Now, PUSH
all the neighbors of H onto the stack that are in ready state.

1. Print: H]STACK: A

Step 3 - POP the top element from the stack, i.e., A, and print it. Now, PUSH
all the neighbors of A onto the stack that are in ready state.

1. Print: A
2. STACK: B, D

Step 4 - POP the top element from the stack, i.e., D, and print it. Now, PUSH
all the neighbors of D onto the stack that are in ready state.

1. Print: D
2. STACK: B, F

Step 5 - POP the top element from the stack, i.e., F, and print it. Now, PUSH
all the neighbors of F onto the stack that are in ready state.

1. Print: F
2. STACK: B
Step 6 - POP the top element from the stack, i.e., B, and print it. Now, PUSH
all the neighbors of B onto the stack that are in ready state.

1. Print: B
2. STACK: C

Step 7 - POP the top element from the stack, i.e., C, and print it. Now, PUSH
all the neighbors of C onto the stack that are in ready state.

1. Print: C
2. STACK: E, G

Step 8 - POP the top element from the stack, i.e., G and PUSH all the
neighbors of G onto the stack that are in ready state.

1. Print: G
2. STACK: E

Step 9 - POP the top element from the stack, i.e., E and PUSH all the
neighbors of E onto the stack that are in ready state.

1. Print: E
2. STACK:

Now, all the graph nodes have been traversed, and the stack is empty.

You might also like