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

Sorting Techniques

Uploaded by

Sumit Gupta
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views

Sorting Techniques

Uploaded by

Sumit Gupta
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 13

Common Sorting Techniques

Sure, I can help you prepare a comprehensive document on common sorting techniques. We'll start with a summary table comparing various
sorting algorithms, followed by a brief description of each algorithm, and then provide the code in both Java and Python with explanations and
comments.

Summary Table
Worst Case Data
Sorting Average Case
Time Stable Requirement Other Characteristics
Algorithm Time Complexity
Complexity (Online/Offline)
Bubble
O(n^2) O(n^2) Yes Offline Simple but inefficient
Sort
Insertion Efficient for small datasets or
O(n^2) O(n^2) Yes Online
Sort nearly sorted data
Selection
O(n^2) O(n^2) No Offline Simple but inefficient
Sort
Quick Sort O(n log n) O(n^2) No Offline Fast, in-place, but unstable
In-place, not stable, uses heap
Heap Sort O(n log n) O(n log n) No Offline
data structure
Merge
O(n log n) O(n log n) Yes Offline Stable, requires extra space
Sort
Only for integers, uses extra
Counting
O(n + k) O(n + k) Yes Offline space proportional to range of
Sort
input

Descriptions
Bubble Sort

Bubble Sort is a simple sorting algorithm that repeatedly steps through the list, compares adjacent elements, and swaps them if they are in the
wrong order. This process is repeated until the list is sorted. It is known for its simplicity but is highly inefficient for large lists.

Insertion Sort

Insertion Sort works by building a sorted portion of the list one item at a time. It takes each element from the input list and inserts it into the correct
position in the already sorted part of the list. It is efficient for small datasets or lists that are already partially sorted.

Selection Sort

Selection Sort divides the list into a sorted and an unsorted region. It repeatedly selects the smallest (or largest) element from the unsorted region
and moves it to the end of the sorted region. Despite its simplicity, it is inefficient for large lists.

Quick Sort

Quick Sort is a divide-and-conquer algorithm that selects a 'pivot' element and partitions the list into elements less than the pivot and elements
greater than the pivot. The process is then recursively applied to the partitions. It is fast and efficient but not stable.

Heap Sort

Heap Sort uses a binary heap data structure to sort elements. It first builds a max-heap and then repeatedly extracts the maximum element to
build the sorted list. It is an efficient in-place sorting algorithm but not stable.

Merge Sort

Merge Sort is a divide-and-conquer algorithm that divides the list into equal halves, recursively sorts them, and then merges the sorted halves. It is
stable and has consistent performance but requires additional space for the merging process.
Counting Sort

Counting Sort is a non-comparative sorting algorithm that works by counting the occurrences of each unique element in the input list. It then uses
this count to determine the positions of each element in the sorted output. It is efficient for sorting integers but requires extra space proportional to
the range of the input.

Code Implementations
Bubble Sort

Java:

public class BubbleSort {


public static void bubbleSort(int[] array) {
int n = array.length;
boolean swapped;
for (int i = 0; i < n - 1; i++) {
swapped = false;
for (int j = 0; j < n - 1 - i; j++) {
if (array[j] > array[j + 1]) {
// Swap array[j] and array[j + 1]
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
swapped = true;
}
}
// If no elements were swapped, the array is already sorted
if (!swapped) break;
}
}
}

Python:

def bubble_sort(arr):
n = len(arr)
for i in range(n):
swapped = False
for j in range(0, n - i - 1):
if arr[j] > arr[j + 1]:
# Swap arr[j] and arr[j + 1]
arr[j], arr[j + 1] = arr[j + 1], arr[j]
swapped = True
# If no elements were swapped, the array is already sorted
if not swapped:
break

Insertion Sort
Java:
public class InsertionSort {
public static void insertionSort(int[] array) {
for (int i = 1; i < array.length; i++) {
int key = array[i];
int j = i - 1;
// Move elements of array[0..i-1], that are greater than key, to one position ahead
// of their current position
while (j >= 0 && array[j] > key) {
array[j + 1] = array[j];
j = j - 1;
}
array[j + 1] = key;
}
}
}

Python:

def insertion_sort(arr):
for i in range(1, len(arr)):
key = arr[i]
j = i - 1
# Move elements of arr[0..i-1], that are greater than key, to one position ahead
# of their current position
while j >= 0 and key < arr[j]:
arr[j + 1] = arr[j]
j -= 1
arr[j + 1] = key

Selection Sort
Java:
public class SelectionSort {
public static void selectionSort(int[] array) {
int n = array.length;
for (int i = 0; i < n - 1; i++) {
// Find the minimum element in unsorted array
int minIndex = i;
for (int j = i + 1; j < n; j++) {
if (array[j] < array[minIndex]) {
minIndex = j;
}
}
// Swap the found minimum element with the first element
int temp = array[minIndex];
array[minIndex] = array[i];
array[i] = temp;
}
}
}

Python:

def selection_sort(arr):
for i in range(len(arr)):
# Find the minimum element in unsorted array
min_idx = i
for j in range(i + 1, len(arr)):
if arr[j] < arr[min_idx]:
min_idx = j
# Swap the found minimum element with the first element
arr[i], arr[min_idx] = arr[min_idx], arr[i]

Quick Sort
Java:
public class QuickSort {
public static void quickSort(int[] array, int low, int high) {
if (low < high) {
// pi is partitioning index, array[pi] is now at right place
int pi = partition(array, low, high);
// Recursively sort elements before partition and after partition
quickSort(array, low, pi - 1);
quickSort(array, pi + 1, high);
}
}

private static int partition(int[] array, int low, int high) {


int pivot = array[high];
int i = (low - 1); // Index of smaller element
for (int j = low; j < high; j++) {
// If current element is smaller than or equal to pivot
if (array[j] <= pivot) {
i++;
// Swap array[i] and array[j]
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
// Swap array[i + 1] and array[high] (or pivot)
int temp = array[i + 1];
array[i + 1] = array[high];
array[high] = temp;
return i + 1;
}
}

Python:
def quick_sort(arr, low, high):
if low < high:
# pi is partitioning index, arr[pi] is now at right place
pi = partition(arr, low, high)
# Recursively sort elements before partition and after partition
quick_sort(arr, low, pi - 1)
quick_sort(arr, pi + 1, high)

def partition(arr, low, high):


pivot = arr[high]
i = low - 1 # Index of smaller element
for j in range(low, high):
# If current element is smaller than or equal to pivot
if arr[j] <= pivot:
i += 1
# Swap arr[i] and arr[j]
arr[i], arr[j] = arr[j], arr[i]
# Swap arr[i + 1] and arr[high] (or pivot)
arr[i + 1], arr[high] = arr[high], arr[i + 1]
return i + 1

Sorting Techniques in Java Collections and Python's sort Method


Java Collections Framework

The Collections.sort() method in Java uses the Timsort algorithm, which is a hybrid sorting algorithm derived from merge sort and insertion
sort. It is designed to perform well on many kinds of real-world data, providing the following characteristics:

Average Case Time Complexity: O(n log n)


Worst Case Time Complexity: O(n log n)
Stable: Yes
Other Characteristics: Timsort is optimized for sorting runs of already ordered elements and is efficient with real-world data patterns.

Python's sort Method

The sort() method in Python's list and the sorted() function also use Timsort. This algorithm is a hybrid sorting algorithm derived from merge
sort and insertion sort, designed to perform well on many kinds of real-world data. It provides the following characteristics:

Average Case Time Complexity: O(n log n)


Worst Case Time Complexity: O(n log n)
Stable: Yes
Other Characteristics: Timsort is optimized for sorting runs of already ordered elements and is efficient with real-world data patterns.

Both the Java Collections.sort() and Python sort() methods are implemented with Timsort, making them highly efficient and stable for a
wide range of sorting tasks.

Merge Sort

Java:
public class MergeSort {
public static void mergeSort(int[] array, int left, int right) {
if (left < right) {
int mid = (left + right) / 2;

// Sort first and second halves


mergeSort(array, left, mid);
mergeSort(array, mid + 1, right);

// Merge the sorted halves


merge(array, left, mid, right);
}
}

private static void merge(int[] array, int left, int mid, int right) {
int n1 = mid - left + 1;
int n2 = right - mid;

int[] L = new int[n1];


int[] R = new int[n2];

for (int i = 0; i < n1; ++i) {


L[i] = array[left + i];
}
for (int j = 0; j < n2; ++j) {
R[j] = array[mid + 1 + j];
}

int i = 0, j = 0;
int k = left;
while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
array[k] = L[i];
i++;
} else {
array[k] = R[j];
j++;
}
k++;
}

while (i < n1) {


array[k] = L[i];
i++;
k++;
}

while (j < n2) {


array[k] = R[j];
j++;
k++;
}
}
}

Python:

def merge_sort(arr):
if len(arr) > 1:
mid = len(arr) // 2 # Finding the mid of the array
L = arr[:mid] # Dividing the elements into 2 halves
R = arr[mid:]

merge_sort(L) # Sorting the first half


merge_sort(R) # Sorting the second half

i = j = k = 0

# Copy data to temp arrays L[] and R[]


while i < len(L) and j < len(R):
if L[i] <= R[j]:
arr[k] = L[i]
i += 1
else:
arr[k] = R[j]
j += 1
k += 1

# Checking if any element was left


while i < len(L):
arr[k] = L[i]
i += 1
k += 1

while j < len(R):


arr[k] = R[j]
j += 1
k += 1

Counting Sort

Java:
public class CountingSort {
public static void countingSort(int[] array) {
int max = getMax(array);
int[] count = new int[max + 1];
int[] output = new int[array.length];

// Store count of each character


for (int i = 0; i < array.length; i++) {
count[array[i]]++;
}

// Change count[i] so that count[i] now contains actual position of this character in output array
for (int i = 1; i <= max; i++) {
count[i] += count[i - 1];
}

// Build the output array


for (int i = array.length - 1; i >= 0; i--) {
output[count[array[i]] - 1] = array[i];
count[array[i]]--;
}

// Copy the output array to array, so that array now contains sorted characters
System.arraycopy(output, 0, array, 0, array.length);
}

private static int getMax(int[] array) {


int max = array[0];
for (int i = 1; i < array.length; i++) {
if (array[i] > max) {
max = array[i];
}
}
return max;
}
}

Python:
def counting_sort(arr):
max_val = max(arr)
count = [0] * (max_val + 1)
output = [0] * len(arr)

# Store count of each character


for num in arr:
count[num] += 1

# Change count[i] so that count[i] now contains actual position of this character in output array
for i in range(1, len(count)):
count[i] += count[i - 1]

# Build the output array


for num in arr[::-1]:
output[count[num] - 1] = num
count[num] -= 1

# Copy the output array to arr, so that arr now contains sorted characters
for i in range(len(arr)):
arr[i] = output[i]

Heap Sort

Java:
public class HeapSort {
public static void heapSort(int[] array) {
int n = array.length;

// Build heap (rearrange array)


for (int i = n / 2 - 1; i >= 0; i--) {
heapify(array, n, i);
}

// One by one extract elements from heap


for (int i = n - 1; i >= 0; i--) {
// Move current root to end
int temp = array[0];
array[0] = array[i];
array[i] = temp;

// Call max heapify on the reduced heap


heapify(array, i, 0);
}
}

private static void heapify(int[] array, int n, int i) {


int largest = i; // Initialize largest as root
int left = 2 * i + 1; // left = 2*i + 1
int right = 2 * i + 2; // right = 2*i + 2

// If left child is larger than root


if (left < n && array[left] > array[largest]) {
largest = left;
}

// If right child is larger than largest so far


if (right < n && array[right] > array[largest]) {
largest = right;
}

// If largest is not root


if (largest != i) {
int swap = array[i];
array[i] = array[largest];
array[largest] = swap;

// Recursively heapify the affected sub-tree


heapify(array, n, largest);
}
}
}

Python:
def heap_sort(arr):
n = len(arr)

# Build a maxheap.
for i in range(n // 2 - 1, -1, -1):
heapify(arr, n, i)

# One by one extract elements


for i in range(n - 1, 0, -1):
arr[i], arr[0] = arr[0], arr[i] # swap
heapify(arr, i, 0)

def heapify(arr, n, i):


largest = i # Initialize largest as root
left = 2 * i + 1 # left = 2*i + 1
right = 2 * i + 2 # right = 2*i + 2

# See if left child of root exists and is greater than root


if left < n and arr[left] > arr[largest]:
largest = left

# See if right child of root exists and is greater than root


if right < n and arr[right] > arr[largest]:
largest = right

# Change root, if needed


if largest != i:
arr[i], arr[largest] = arr[largest], arr[i] # swap

# Heapify the root.


heapify(arr, n, largest)

Descriptions

Bubble Sort: A simple sorting algorithm that repeatedly steps through the

list, compares adjacent elements, and swaps them if they are in the wrong order. It is easy to understand but highly inefficient for large lists.

Insertion Sort: Works by building a sorted portion of the list one item at a time. It is efficient for small datasets or lists that are already partially
sorted.

Selection Sort: Divides the list into a sorted and an unsorted region. Repeatedly selects the smallest (or largest) element from the unsorted
region and moves it to the end of the sorted region. Simple but inefficient for large lists.

Quick Sort: A divide-and-conquer algorithm that selects a 'pivot' element and partitions the list into elements less than the pivot and elements
greater than the pivot. Recursively applied to partitions. Fast and efficient but not stable.

Heap Sort: Uses a binary heap data structure to sort elements. Builds a max-heap and repeatedly extracts the maximum element to build the
sorted list. Efficient and in-place but not stable.

Merge Sort: A divide-and-conquer algorithm that divides the list into equal halves, recursively sorts them, and then merges the sorted halves.
Stable and consistent performance but requires additional space for merging.
Counting Sort: A non-comparative sorting algorithm that works by counting the occurrences of each unique element in the input list and uses this
count to determine the positions of each element in the sorted output. Efficient for sorting integers but requires extra space proportional to the
range of the input.

This document covers the summary table, explanations, and code implementations for each sorting algorithm, providing a solid foundation for
understanding common sorting techniques in computer science.

You might also like