Read at your own pace. Code execution, quizzes, progress tracking, and the AI tutor are available in the interactive view with JavaScript enabled.
Introduction
This tutorial is about two awesome, non-comparison-based sorting algorithms. While many sorting algorithms require a comparator function that compares two values at a time, these two and their family of non-comparison methods rely on other techniques instead. We'll cover counting sort and radix sort, which are both very efficient. Bucket sort is another one, but it's a close enough cousin of radix sort that we'll point to other references for more information on it.
Before going into details, we must keep in mind that any sorting algorithm has to scan the unsorted array at least once. This provides us the following important rule:
Any sorting algorithm will take at least O(n) time
This statement constrains the best possible shortest sorting time - we cannot sort an array in a time complexity less than O(n). Of course, there are sorting algorithms which take up significantly more time. Given this ambitious target of O(n), let's look at how counting sort and radix sort stack up.
Here's a preview of the final implementations, but we'll be sure to walk you through the theory before revealing them again!
```py
def counting_sort(arr):
n = 0
max_num = max(arr)
counts = [0 for _ in range(max_num + 1)]
# Set up keys
for i in range(max_num + 1):
counts[i] = 0
# Count
for num in arr:
counts[num] += 1
# Order by count
for i in range(max_num + 1):
for j in range(0, counts[i]):
arr[n] = i
n += 1
return arr
def radix_sort(nums):
RADIX = 10
placement = 1
max_digit = max(nums)
while placement <= max_digit:
# declare and initialize empty buckets
buckets: list[list] = [[] for _ in range(RADIX)]
# split nums between the buckets
for i in nums:
tmp = int((i / placement) % RADIX)
buckets[tmp].append(i)
# put each buckets' contents into nums
a = 0
for bucket in range(RADIX):
for i in buckets[bucket]:
nums[a] = i
a += 1
# move to next
placement *= RADIX
return nums
print(counting_sort([5, 0, 65, 4, 10]))
print(radix_sort([5, 0, 65, 4, 10]))
```
```js
function countingSort(arr) {
let counts = [];
let n = 0;
let max = Math.max(...arr);
// Set up keys
for (let i = 0; i <= max; i++) {
counts[i] = 0;
}
// Count
for (let i = 0; i < arr.length; i++) {
counts[arr[i]]++;
}
// Order by count
for (let i = 0; i <= max; i++) {
for (let j = 0; j < counts[i]; j++) {
arr[n] = i;
n++;
}
}
return arr;
}
function getDigit(num, i) {
return Math.floor(Math.abs(num) / Math.pow(10, i)) % 10;
}
function digitCount(num) {
if (num === 0) return 1;
return Math.floor(Math.log10(Math.abs(num))) + 1;
}
function radixSort(arr) {
let maxDigits = 0;
for (let i = 0; i < arr.length; i++) {
maxDigits = Math.max(maxDigits, digitCount(arr[i]));
}
for (let k = 0; k < maxDigits; k++) {
let buckets = Array.from({ length: 10 }, () => []);
for (let i = 0; i < arr.length; i++) {
let digit = getDigit(arr[i], k);
buckets[digit].push(arr[i]);
}
arr = [].concat(...buckets);
}
return arr;
}
console.log(radixSort([5, 0, 65, 4, 10]))
console.log(countingSort([5, 0, 65, 4, 10]));
```
```java
import java.util.*;
class Main {
static class countSort
{
static int []count;
static int [] sorted;
static int maxArray(int[] arr)
{
int max=arr[0];
for (int i=1;i<arr.length;++i)
{
if (arr[i]>max)
max = arr[i];
}
return max;
}
static int[] sort(int[]X)
{
int i;
int max = maxArray(X);
count = new int[max+1];
//initialize to zero
for (i=0;i<count.length;++i)
count[i] = 0;
//add counts to count array
for(i=0;i<X.length;++i)
{
count[X[i]] = count[X[i]] + 1;
}
//accumulate the counts
int total = count[0];
count[0] = 0;
for(i=1;i<count.length;++i)
{
int temp = total;
total = temp+count[i];
count[i] = temp;
}
sorted = new int[X.length];
//fill up the output array sorted
for( i=0;i<X.length;++i)
{
sorted[count[X[i]]] = X[i];
count[X[i]]++;
}
//put sorted in X
for( i=0;i<X.length;++i)
{
X[i] = sorted[i];
}
return X;
}
}
static class radixSort
{
static final int BASE=10;
static ArrayList<Integer>[] bucket;
static int maxArray(int[] arr)
{
int max=arr[0];
for (int i=1;i<arr.length;++i)
{
if (arr[i]>max)
max = arr[i];
}
return max;
}
static void initializeBucket()
{
bucket = new ArrayList[BASE];
for (int i=0;i<bucket.length;++i)
bucket[i] = new ArrayList<Integer>();
}
static void addXToBucket(int []X,int digit)
{
int ind;
for (int i=0;i<X.length;++i)
{
ind = (X[i]/digit)%BASE;
bucket[ind].add(X[i]);
}
}
static void addBucketToX(int []X)
{
int Xind = 0;
for (int i=0;i<bucket.length;++i)
{
for (int j=0;j<bucket[i].size();++j)
{
X[Xind] = bucket[i].get(j);
Xind++;
}
bucket[i].clear();
}
}
public static int[] sort(int [] X)
{
int max=maxArray(X);
initializeBucket();
boolean sorted = false;
int digit = 1;
while(!sorted)
{
addXToBucket(X,digit);
addBucketToX(X);
digit = digit*10;
if (max/digit==0)
sorted = true;
}
return X;
}
}
public static void main(String args[]){
int[] unsorted = {5, 0, 65, 4, 10};
System.out.print("Unsorted array: ");
System.out.println(Arrays.toString(unsorted));
System.out.print("Sorted: ");
System.out.println(Arrays.toString(countSort.sort(unsorted)));
System.out.println(Arrays.toString(radixSort.sort(unsorted)));
}
}
```
CONTINUE WITH ALGODAILY PREMIUM
Keep going with the complete tutorial.
Unlock the remaining explanations and exercises, alongside the full learning library.