Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added radix sort and Shell sort #1948

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 162 additions & 0 deletions docs/sortings/radix-sort.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
---
id: radix-sort
title: Radix Sort
sidebar_label: Radix Sort
description: "Learn about Radix Sort, a non-comparative integer sorting algorithm that processes numbers digit by digit."
tags: [dsa, algorithms, sorting]
---

### Definition:
Radix Sort is a non-comparative sorting algorithm that sorts numbers by processing individual digits. The algorithm processes each digit starting from the least significant digit (LSD) or the most significant digit (MSD), depending on the implementation. Radix Sort is efficient when sorting large sets of integers or strings.

### Characteristics:
- **Non-Comparative**:
Unlike comparison-based algorithms (like QuickSort or MergeSort), Radix Sort doesn't compare elements directly. Instead, it sorts elements based on their individual digits or characters.

- **Stable**:
Radix Sort is a stable sorting algorithm, meaning that when two elements have the same value, their original relative order is preserved.

- **Efficient for Specific Data Types**:
Radix Sort is very efficient for sorting integers or strings with a fixed number of digits or characters. Its performance is independent of the size of the values themselves, but depends on the number of digits or characters in the input.

### Steps Involved:
1. **Find the Maximum Element**:
Identify the maximum number in the input array to determine the number of digits to process.

2. **Sort by Each Digit**:
Starting from the least significant digit, group the numbers by their digit value and sort them. Repeat this process for each digit, moving towards the most significant digit.

3. **Repeat for All Digits**:
Perform sorting for each digit until all digits have been processed. The array will then be fully sorted.

### Time Complexity:
- **Time Complexity**:
- $O(n \cdot k)$, where `n` is the number of elements and `k` is the number of digits in the largest number.
Radix Sort is linear in the number of elements when the number of digits (`k`) is relatively small or constant.

- **Space Complexity**:
- $O(n + k)$, due to the space required for the counting sort step.

### Example:
Consider the following array of integers:
`[170, 45, 75, 90, 802, 24, 2, 66]`

Step-by-step execution (starting with the least significant digit):

1. **First Pass (Least Significant Digit)**:
`[170, 90, 802, 2, 24, 45, 75, 66]`

2. **Second Pass (Second Least Significant Digit)**:
`[802, 2, 24, 45, 66, 170, 75, 90]`

3. **Third Pass (Most Significant Digit)**:
`[2, 24, 45, 66, 75, 90, 170, 802]`

### C++ Implementation:
```cpp
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// Function to perform counting sort based on a specific digit
void countingSort(vector<int>& arr, int exp) {
int n = arr.size();
vector<int> output(n);
vector<int> count(10, 0);

// Store count of occurrences of digits
for (int i = 0; i < n; i++) {
count[(arr[i] / exp) % 10]++;
}

// Change count[i] so that count[i] contains the actual position of the digit in output[]
for (int i = 1; i < 10; i++) {
count[i] += count[i - 1];
}

// Build the output array
for (int i = n - 1; i >= 0; i--) {
output[count[(arr[i] / exp) % 10] - 1] = arr[i];
count[(arr[i] / exp) % 10]--;
}

// Copy the output array to arr[], so that arr[] now contains sorted numbers
for (int i = 0; i < n; i++) {
arr[i] = output[i];
}
}

// Function to implement radix sort
void radixSort(vector<int>& arr) {
// Find the maximum number to know the number of digits
int maxNum = *max_element(arr.begin(), arr.end());

// Apply counting sort to sort elements based on each digit
for (int exp = 1; maxNum / exp > 0; exp *= 10) {
countingSort(arr, exp);
}
}

int main() {
vector<int> arr = {170, 45, 75, 90, 802, 24, 2, 66};
radixSort(arr);

cout << "Sorted array: ";
for (int num : arr) {
cout << num << " ";
}
cout << endl;

return 0;
}

import java.util.*;

public class RadixSort {

// Function to perform counting sort based on a specific digit
public static void countingSort(int[] arr, int exp) {
int n = arr.length;
int[] output = new int[n];
int[] count = new int[10];

// Store count of occurrences of digits
for (int i = 0; i < n; i++) {
count[(arr[i] / exp) % 10]++;
}

// Change count[i] so that count[i] contains the actual position of the digit in output[]
for (int i = 1; i < 10; i++) {
count[i] += count[i - 1];
}

// Build the output array
for (int i = n - 1; i >= 0; i--) {
output[count[(arr[i] / exp) % 10] - 1] = arr[i];
count[(arr[i] / exp) % 10]--;
}

// Copy the output array to arr[], so that arr[] now contains sorted numbers
System.arraycopy(output, 0, arr, 0, n);
}

// Function to implement radix sort
public static void radixSort(int[] arr) {
// Find the maximum number to know the number of digits
int maxNum = Arrays.stream(arr).max().getAsInt();

// Apply counting sort to sort elements based on each digit
for (int exp = 1; maxNum / exp > 0; exp *= 10) {
countingSort(arr, exp);
}
}

public static void main(String[] args) {
int[] arr = {170, 45, 75, 90, 802, 24, 2, 66};
radixSort(arr);

System.out.println("Sorted array: " + Arrays.toString(arr));
}
}```
128 changes: 128 additions & 0 deletions docs/sortings/shell-sort .md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
---
id: shell-sort
title: Shell Sort
sidebar_label: Shell Sort
description: "Learn about Shell Sort, an in-place comparison-based sorting algorithm that generalizes insertion sort to allow the exchange of items that are far apart."
tags: [dsa, algorithms, sorting]
---

### Definition:
Shell Sort is an in-place comparison-based sorting algorithm that generalizes insertion sort to allow the exchange of items that are far apart. It works by initially sorting elements far apart from each other and progressively reducing the gap between elements to be compared. This approach helps to move elements more efficiently compared to a simple insertion sort.

### Characteristics:
- **In-Place Sorting**:
Shell Sort does not require any extra space for sorting, making it an in-place algorithm.

- **Adaptive**:
Shell Sort's efficiency improves based on the gap sequence used. A better gap sequence results in better performance.

- **Improvement over Insertion Sort**:
By allowing elements far apart to be compared and swapped, Shell Sort reduces the number of shifts required, thus improving on the basic insertion sort, especially for larger datasets.

### Steps Involved:
1. **Choose a Gap Sequence**:
Select a sequence of gap values. The choice of gap sequence can greatly influence the algorithm's performance.

2. **Compare and Swap Elements**:
Starting with the largest gap, compare elements that are `gap` positions apart and swap them if necessary. This step is similar to insertion sort but with a larger gap between compared elements.

3. **Reduce the Gap**:
After the initial pass, reduce the gap and repeat the process until the gap is reduced to 1, at which point the algorithm performs a final insertion sort.

4. **Final Insertion Sort**:
When the gap becomes 1, the algorithm essentially performs an insertion sort, with the list nearly sorted from the previous passes.

### Time Complexity:
- **Best Case**: $O(n \log n)$, depending on the gap sequence.
- **Average Case**: $O(n^{3/2})$ or $O(n \log^2 n)$, depending on the gap sequence used.
- **Worst Case**: $O(n^2)$, using the original gap sequence.

### Space Complexity:
- **Space Complexity: $O(1)$**
Shell Sort is an in-place algorithm, requiring only a constant amount of extra space.

### Example:
Consider the following array of integers:
`[5, 2, 9, 1, 5, 6]`

Step-by-step execution with gap sequence `[3, 1]`:

1. **First Pass (Gap = 3)**:
- Compare elements 3 positions apart: `5` and `1`, `2` and `5`, `9` and `6`.
- Array after first pass: `[1, 2, 5, 5, 9, 6]`.

2. **Second Pass (Gap = 1)**:
- Perform an insertion sort with a gap of 1: Compare `5` and `5`, `9` and `6`.
- Array after second pass: `[1, 2, 5, 5, 6, 9]`.

### C++ Implementation:
```cpp
#include <iostream>
#include <vector>

using namespace std;

// Function to perform shell sort
void shellSort(vector<int>& arr) {
int n = arr.size();

// Start with a large gap, and reduce the gap
for (int gap = n / 2; gap > 0; gap /= 2) {
// Perform a gapped insertion sort
for (int i = gap; i < n; i++) {
int temp = arr[i];
int j = i;
// Shift earlier gap-sorted elements up until the correct location for arr[i] is found
while (j >= gap && arr[j - gap] > temp) {
arr[j] = arr[j - gap];
j -= gap;
}
arr[j] = temp;
}
}
}

int main() {
vector<int> arr = {5, 2, 9, 1, 5, 6};
shellSort(arr);

cout << "Sorted array: ";
for (int num : arr) {
cout << num << " ";
}
cout << endl;

return 0;
}

import java.util.*;

public class ShellSort {

// Function to perform shell sort
public static void shellSort(int[] arr) {
int n = arr.length;

// Start with a large gap, and reduce the gap
for (int gap = n / 2; gap > 0; gap /= 2) {
// Perform a gapped insertion sort
for (int i = gap; i < n; i++) {
int temp = arr[i];
int j = i;
// Shift earlier gap-sorted elements up until the correct location for arr[i] is found
while (j >= gap && arr[j - gap] > temp) {
arr[j] = arr[j - gap];
j -= gap;
}
arr[j] = temp;
}
}
}

public static void main(String[] args) {
int[] arr = {5, 2, 9, 1, 5, 6};
shellSort(arr);

System.out.println("Sorted array: " + Arrays.toString(arr));
}
}```