Data update
This commit is contained in:
parent
81fd053722
commit
52a6ef48dd
10248 changed files with 63654 additions and 6775 deletions
|
|
@ -0,0 +1,193 @@
|
|||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <numeric>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
std::random_device random_device;
|
||||
std::mt19937 generator(random_device());
|
||||
|
||||
int32_t measure_execution_time(const std::function<void(std::vector<int32_t>)>& sort, const std::vector<int32_t>& sequence) {
|
||||
const auto start_time = std::chrono::high_resolution_clock::now();
|
||||
sort(sequence);
|
||||
const auto stop_time = std::chrono::high_resolution_clock::now();
|
||||
return std::chrono::duration_cast<std::chrono::microseconds>(stop_time - start_time).count();
|
||||
}
|
||||
|
||||
std::vector<int32_t> ones(const int32_t& n) {
|
||||
std::vector<int32_t> result(n, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<int32_t> ascending(const int32_t& n) {
|
||||
std::vector<int32_t> result(n);
|
||||
std::iota(result.begin(), result.end(), 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<int32_t> random(const int32_t& n) {
|
||||
std::vector<int32_t> result(n);
|
||||
std::uniform_int_distribution<int32_t> distribution(1, 10 * n);
|
||||
for ( int32_t i = 0; i < n; ++i ) {
|
||||
result[i] = distribution(generator);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::function<void(const std::vector<int32_t>&)> bubble_sort = [](std::vector<int32_t> vec) {
|
||||
int32_t n = vec.size();
|
||||
while ( n != 0 ) {
|
||||
int32_t n2 = 0;
|
||||
for ( int32_t i = 1; i < n; ++i ) {
|
||||
if ( vec[i - 1] > vec[i] ) {
|
||||
const int32_t temp = vec[i];
|
||||
vec[i] = vec[i - 1];
|
||||
vec[i - 1] = temp;
|
||||
n2 = i;
|
||||
}
|
||||
}
|
||||
n = n2;
|
||||
}
|
||||
};
|
||||
|
||||
std::function<void(const std::vector<int32_t>&)> insertion_sort = [](std::vector<int32_t> vec) {
|
||||
for ( uint32_t index = 1; index < vec.size(); ++index ) {
|
||||
const int32_t value = vec[index];
|
||||
int32_t subIndex = index - 1;
|
||||
while ( subIndex >= 0 && vec[subIndex] > value ) {
|
||||
vec[subIndex + 1] = vec[subIndex];
|
||||
subIndex -= 1;
|
||||
}
|
||||
vec[subIndex + 1] = value;
|
||||
}
|
||||
};
|
||||
|
||||
void quick_sort_recursive(std::vector<int32_t>& vec, const int32_t& first, const int32_t& last) {
|
||||
if ( last - first < 1 ) {
|
||||
return;
|
||||
}
|
||||
const int32_t pivot = vec[first + ( last - first ) / 2];
|
||||
int32_t left = first;
|
||||
int32_t right = last;
|
||||
while ( left <= right ) {
|
||||
while ( vec[left] < pivot ) {
|
||||
left += 1;
|
||||
}
|
||||
while ( vec[right] > pivot ) {
|
||||
right -= 1;
|
||||
}
|
||||
if ( left <= right ) {
|
||||
const int32_t temp = vec[left];
|
||||
vec[left] = vec[right];
|
||||
vec[right] = temp;
|
||||
left += 1;
|
||||
right -= 1;
|
||||
}
|
||||
}
|
||||
if ( first < right ) {
|
||||
quick_sort_recursive(vec, first, right);
|
||||
}
|
||||
if ( left < last ) {
|
||||
quick_sort_recursive(vec, left, last);
|
||||
}
|
||||
}
|
||||
|
||||
std::function<void(const std::vector<int32_t>&)> quick_sort = [](std::vector<int32_t> vec) {
|
||||
quick_sort_recursive(vec, 0, vec.size() - 1);
|
||||
};
|
||||
|
||||
void counting_sort(const std::vector<int32_t>& vec, const int32_t& exponent) {
|
||||
const int32_t vec_size = vec.size();
|
||||
std::vector<int32_t> output(vec_size, 0);
|
||||
std::vector<int32_t> count(10, 0);
|
||||
for ( int32_t i = 0; i < vec_size; ++i ) {
|
||||
const int32_t t = ( vec[i] / exponent ) % 10;
|
||||
count[t] += 1;
|
||||
}
|
||||
for ( int32_t i = 1; i <= 9; ++i ) {
|
||||
count[i] += count[i - 1];
|
||||
}
|
||||
for ( int32_t i = vec_size - 1; i >= 0; --i ) {
|
||||
const int32_t t = ( vec[i] / exponent ) % 10;
|
||||
output[count[t] - 1] = vec[i];
|
||||
count[t] -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
std::function<void(const std::vector<int32_t>&)> radix_sort = [](std::vector<int32_t> vec) {
|
||||
const int32_t min = *min_element(vec.begin(), vec.end());
|
||||
if ( min < 0 ) { // If there are any negative numbers, make all the numbers positive
|
||||
std::for_each(vec.begin(), vec.end(), [min](int32_t& n) { n -= min; });
|
||||
}
|
||||
const int32_t max = *std::max_element(vec.begin(), vec.end());
|
||||
int32_t exponent = 1;
|
||||
while ( max / exponent > 0 ) {
|
||||
counting_sort(vec, exponent);
|
||||
exponent *= 10;
|
||||
}
|
||||
if ( min < 0 ) { // If there were any negative numbers, return the array to its original values
|
||||
std::for_each(vec.begin(), vec.end(), [min](int32_t& n) { n += min; });
|
||||
}
|
||||
};
|
||||
|
||||
std::function<void(const std::vector<int32_t>&)> shell_sort = [](std::vector<int32_t> vec) {
|
||||
for ( int32_t gap : { 701, 301, 132, 57, 23, 10, 4, 1 } ) { // Marcin Ciura's gap sequence
|
||||
for ( uint32_t i = gap; i < vec.size(); ++i ) {
|
||||
const int32_t temp = vec[i];
|
||||
int32_t j = i;
|
||||
while ( j >= gap && vec[j - gap] > temp ) {
|
||||
vec[j] = vec[j - gap];
|
||||
j -= gap;
|
||||
}
|
||||
vec[j] = temp;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
const uint32_t repetitions = 10;
|
||||
std::vector<uint32_t> lengths = { 1, 10, 100, 1'000, 10'000, 100'000 };
|
||||
std::vector<std::function<void(const std::vector<int32_t>&)>> sorts =
|
||||
{ bubble_sort, insertion_sort, quick_sort, radix_sort, shell_sort };
|
||||
std::vector<std::string> sort_titles = { "Bubble", "Insert", "Quick ", "Radix ", "Shell " };
|
||||
std::vector<std::string> sequence_titles = { "All Ones", "Ascending", "Random" };
|
||||
|
||||
std::vector<std::vector<std::vector<int64_t>>> totals =
|
||||
{ 3, std::vector { sorts.size(), std::vector<int64_t>(lengths.size(), 0) } };
|
||||
for ( uint32_t k = 0; k < lengths.size(); ++k ) {
|
||||
const int32_t n = lengths[k];
|
||||
std::vector<std::vector<int32_t>> sequences = { ones(n), ascending(n), random(n) };
|
||||
for ( uint32_t repetition = 0; repetition < repetitions; ++repetition ) {
|
||||
for ( uint32_t i = 0; i < sequences.size(); ++i ) {
|
||||
for ( uint32_t j = 0; j < sorts.size(); ++j ) {
|
||||
totals[i][j][k] += measure_execution_time(sorts[j], sequences[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "All timings in microseconds." << "\n\n";
|
||||
std::cout << "Sequence length";
|
||||
for ( const uint32_t& length : lengths ) {
|
||||
std::cout << std::setw(10) << length;
|
||||
}
|
||||
std::cout << "\n\n";
|
||||
|
||||
for ( uint32_t i = 0; i < sequence_titles.size(); ++i ) {
|
||||
std::cout << " " + sequence_titles[i] + ":" << "\n";
|
||||
for ( uint32_t j = 0; j < sorts.size(); ++j ) {
|
||||
std::cout << " " + sort_titles[j] + " ";
|
||||
for ( uint32_t k = 0; k < lengths.size(); ++k ) {
|
||||
const int64_t execution_time = totals[i][j][k] / repetitions;
|
||||
std::cout << std::setw(10) << execution_time;
|
||||
}
|
||||
std::cout << "\n";
|
||||
}
|
||||
std::cout << "\n\n";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,192 @@
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public final class ComparingSortingAlgorithmsPerformance {
|
||||
|
||||
public static void main(String[] args) {
|
||||
final int repetitions = 10;
|
||||
List<Integer> lengths = List.of( 1, 10, 100, 1_000, 10_000, 100_000 );
|
||||
List<Consumer<int[]>> sorts = List.of( bubbleSort, insertionSort, quickSort, radixSort, shellSort );
|
||||
|
||||
// Allow the JVM to compile the sort functions before timings start
|
||||
for ( Consumer<int[]> sort : sorts ) {
|
||||
sort.accept( new int[] { 1 } );
|
||||
}
|
||||
|
||||
List<String> sortTitles = List.of( "Bubble", "Insert", "Quick ", "Radix ", "Shell " );
|
||||
List<String> sequenceTitles = List.of( "All Ones", "Ascending", "Random" );
|
||||
|
||||
long[][][] totals = new long[sequenceTitles.size()][sorts.size()][lengths.size()];
|
||||
for ( int k = 0; k < lengths.size(); k++ ) {
|
||||
final int n = lengths.get(k);
|
||||
List<int[]> sequences = List.of( ones.apply(n), ascending.apply(n), random.apply(n) );
|
||||
for ( int repetition = 0; repetition < repetitions; repetition++ ) {
|
||||
for ( int i = 0; i < sequences.size(); i++ ) {
|
||||
for ( int j = 0; j < sorts.size(); j++ ) {
|
||||
totals[i][j][k] += measureExecutionTime(sorts.get(j), sequences.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("All timings in microseconds." + System.lineSeparator());
|
||||
System.out.print("Sequence length");
|
||||
for ( int length : lengths ) {
|
||||
System.out.print(String.format("%8d ", length));
|
||||
}
|
||||
System.out.println(System.lineSeparator());
|
||||
|
||||
for ( int i = 0; i < sequenceTitles.size(); i++ ) {
|
||||
System.out.println(" " + sequenceTitles.get(i) + ":");
|
||||
for ( int j = 0; j < sorts.size(); j++ ) {
|
||||
System.out.print(" " + sortTitles.get(j) + " ");
|
||||
for ( int k = 0; k < lengths.size(); k++ ) {
|
||||
final long executionTime = totals[i][j][k] / repetitions;
|
||||
System.out.print(String.format("%8d ", executionTime));
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
System.out.println(System.lineSeparator());
|
||||
}
|
||||
}
|
||||
|
||||
private static Consumer<int[]> bubbleSort = array -> {
|
||||
int n = array.length;
|
||||
while ( n != 0 ) {
|
||||
int n2 = 0;
|
||||
for ( int i = 1; i < n; i++ ) {
|
||||
if ( array[i - 1] > array[i] ) {
|
||||
final int temp = array[i];
|
||||
array[i] = array[i - 1];
|
||||
array[i - 1] = temp;
|
||||
n2 = i;
|
||||
}
|
||||
}
|
||||
n = n2;
|
||||
}
|
||||
};
|
||||
|
||||
private static Consumer<int[]> insertionSort = array -> {
|
||||
for ( int index = 1; index < array.length; index++ ) {
|
||||
final int value = array[index];
|
||||
int subIndex = index - 1;
|
||||
while ( subIndex >= 0 && array[subIndex] > value ) {
|
||||
array[subIndex + 1] = array[subIndex];
|
||||
subIndex -= 1;
|
||||
}
|
||||
array[subIndex + 1] = value;
|
||||
}
|
||||
};
|
||||
|
||||
private static Consumer<int[]> quickSort = array -> {
|
||||
final class LocalClass {
|
||||
|
||||
private static void quickSortRecursive(int[] array, int first, int last) {
|
||||
if ( last - first < 1 ) {
|
||||
return;
|
||||
}
|
||||
final int pivot = array[first + ( last - first ) / 2];
|
||||
int left = first;
|
||||
int right = last;
|
||||
while ( left <= right ) {
|
||||
while ( array[left] < pivot ) {
|
||||
left += 1;
|
||||
}
|
||||
while ( array[right] > pivot ) {
|
||||
right -= 1;
|
||||
}
|
||||
if ( left <= right ) {
|
||||
final int temp = array[left];
|
||||
array[left] = array[right];
|
||||
array[right] = temp;
|
||||
left += 1;
|
||||
right -= 1;
|
||||
}
|
||||
}
|
||||
if ( first < right ) {
|
||||
quickSortRecursive(array, first, right);
|
||||
}
|
||||
if ( left < last ) {
|
||||
quickSortRecursive(array, left, last);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LocalClass.quickSortRecursive(array, 0, array.length - 1);
|
||||
};
|
||||
|
||||
private static Consumer<int[]> radixSort = array -> {
|
||||
final class LocalClass {
|
||||
|
||||
private static void countingSort(int[] array, int exponent) {
|
||||
final int n = array.length;
|
||||
int[] output = new int[n];
|
||||
int[] count = new int[10];
|
||||
for ( int i = 0; i < n; i++ ) {
|
||||
final int t = ( array[i] / exponent ) % 10;
|
||||
count[t] += 1;
|
||||
}
|
||||
for ( int i = 1; i <= 9; i++ ) {
|
||||
count[i] += count[i - 1];
|
||||
}
|
||||
for ( int i = n - 1; i >= 0; i-- ) {
|
||||
final int t = ( array[i] / exponent ) % 10;
|
||||
output[count[t] - 1] = array[i];
|
||||
count[t] -= 1;
|
||||
}
|
||||
for ( int i = 0; i < n; i++ ) {
|
||||
array[i] = output[i];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
final int min = Arrays.stream(array).min().getAsInt();
|
||||
if ( min < 0 ) { // If there are any negative numbers, make all the numbers positive
|
||||
array = Arrays.stream(array).map( i -> i - min).toArray();
|
||||
}
|
||||
final int max = Arrays.stream(array).max().getAsInt();
|
||||
int exponent = 1;
|
||||
while ( max / exponent > 0 ) {
|
||||
LocalClass.countingSort(array, exponent);
|
||||
exponent *= 10;
|
||||
}
|
||||
if ( min < 0 ) { // If there were any negative numbers, return the array to its original values
|
||||
array = Arrays.stream(array).map( i -> i + min).toArray();
|
||||
}
|
||||
};
|
||||
|
||||
private static Consumer<int[]> shellSort = array -> {
|
||||
for ( int gap : new int[] { 701, 301, 132, 57, 23, 10, 4, 1 } ) { // Marcin Ciura's gap sequence
|
||||
for ( int i = gap; i < array.length; i++ ) {
|
||||
final int temp = array[i];
|
||||
int j = i;
|
||||
while ( j >= gap && array[j - gap] > temp ) {
|
||||
array[j] = array[j - gap];
|
||||
j -= gap;
|
||||
}
|
||||
array[j] = temp;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static Function<Integer, int[]> ones =
|
||||
n -> Stream.generate( () -> 1 ).limit(n).mapToInt(Integer::valueOf).toArray();
|
||||
|
||||
private static Function<Integer, int[]> ascending = n -> IntStream.rangeClosed(1, n).toArray();
|
||||
|
||||
private static Function<Integer, int[]> random = n -> new Random().ints(1, 10 * n).limit(n).toArray();
|
||||
|
||||
private static long measureExecutionTime(Consumer<int[]> sort, int[] sequence) {
|
||||
final long startTime = System.nanoTime();
|
||||
sort.accept(sequence);
|
||||
return ( System.nanoTime() - startTime ) / 1_000; // microseconds
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
# 20241006 Perl programming solution
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Time::HiRes qw(time);
|
||||
|
||||
my ($rounds, $size) = (3, 2000);
|
||||
my @allones = (1) x $size;
|
||||
my @sequential = (1 .. $size);
|
||||
my @randomized = map { $sequential[rand @sequential] } 1 .. $size;
|
||||
|
||||
sub insertion_sort {
|
||||
my @a = @_;
|
||||
for my $k (1 .. $#a) {
|
||||
my ($j, $value) = ($k - 1, $a[$k]);
|
||||
while ($j >= 0 && $a[$j] > $value) {
|
||||
$a[$j + 1] = $a[$j];
|
||||
$j--;
|
||||
}
|
||||
$a[$j + 1] = $value;
|
||||
}
|
||||
return @a;
|
||||
}
|
||||
|
||||
sub merge_sort {
|
||||
my @a = @_;
|
||||
return @a if @a <= 1;
|
||||
|
||||
my $m = int(@a / 2);
|
||||
my @l = merge_sort(@a[0 .. $m - 1]);
|
||||
my @r = merge_sort(@a[$m .. $#a]);
|
||||
|
||||
return (@l, @r) if $l[-1] <= $r[0];
|
||||
|
||||
my @result;
|
||||
while (@l && @r) {
|
||||
push @result, $l[0] <= $r[0] ? shift @l : shift @r;
|
||||
}
|
||||
push @result, @l, @r;
|
||||
return @result;
|
||||
}
|
||||
|
||||
sub quick_sort {
|
||||
my @data = @_;
|
||||
return @data if @data <= 1;
|
||||
|
||||
my $pivot_index = int(rand(@data));
|
||||
my $pivot = $data[$pivot_index];
|
||||
|
||||
@data = grep { $_ != $pivot } @data;
|
||||
|
||||
my (@left, @right);
|
||||
foreach my $x (@data) {
|
||||
$x < $pivot ? push @left, $x : push @right, $x;
|
||||
}
|
||||
return (quick_sort(@left), $pivot, quick_sort(@right));
|
||||
}
|
||||
|
||||
sub comparesorts {
|
||||
my ($rounds, @tosort) = @_;
|
||||
my ($iavg, $mavg, $qavg);
|
||||
|
||||
foreach my $sort_type (('i', 'm', 'q') x $rounds) {
|
||||
my @data_copy = @tosort;
|
||||
my $t = time;
|
||||
if ($sort_type eq 'i') {
|
||||
insertion_sort(@data_copy);
|
||||
$iavg += time - $t;
|
||||
} elsif ($sort_type eq 'm') {
|
||||
merge_sort(@data_copy);
|
||||
$mavg += time - $t;
|
||||
} elsif ($sort_type eq 'q') {
|
||||
quick_sort(@data_copy);
|
||||
$qavg += time - $t;
|
||||
}
|
||||
}
|
||||
return ($iavg / $rounds, $mavg / $rounds, $qavg / $rounds);
|
||||
}
|
||||
|
||||
foreach my $test (['ones', @allones], ['presorted', @sequential], ['randomized', @randomized]) {
|
||||
my ($t, @d) = @$test;
|
||||
print "Average sort times for $size $t:\n";
|
||||
my ($i_time, $m_time, $q_time) = comparesorts($rounds, @d);
|
||||
printf "insertion sort %0.9f\n", $i_time;
|
||||
printf "merge sort %0.9f\n", $m_time;
|
||||
printf "quick sort %0.9f\n", $q_time;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue