399 lines
12 KiB
C++
399 lines
12 KiB
C++
#include <iostream>
|
|
#include <chrono>
|
|
#include <random>
|
|
#include <limits>
|
|
#include <algorithm>
|
|
#include <string>
|
|
#include <iomanip>
|
|
#include <fstream>
|
|
#include <clocale>
|
|
|
|
using std::swap;
|
|
|
|
int losowa_liczba(int min, int max)
|
|
{
|
|
static std::default_random_engine gen(std::random_device{}());
|
|
static std::uniform_int_distribution<int> dist;
|
|
return dist(gen, std::uniform_int_distribution<int>::param_type{ min, max });
|
|
}
|
|
|
|
void wypelnij(int* tablica, int rozmiar, int min = 0, int max = std::numeric_limits<int>::max())
|
|
{
|
|
for (int i = 0; i < rozmiar; ++i)
|
|
tablica[i] = losowa_liczba(min, max);
|
|
}
|
|
|
|
bool jest_posortowane(int* tablica, int rozmiar)
|
|
{
|
|
return std::is_sorted(tablica, tablica + rozmiar);
|
|
}
|
|
|
|
double mierz_czas(int* tablica, int rozmiar, void(*funkcja_sortujaca)(int*, int))
|
|
{
|
|
auto start = std::chrono::high_resolution_clock::now();
|
|
funkcja_sortujaca(tablica, rozmiar);
|
|
auto end = std::chrono::high_resolution_clock::now();
|
|
std::chrono::duration<double> duration = end - start;
|
|
return duration.count();
|
|
}
|
|
|
|
/*
|
|
|
|
parametry:
|
|
- funkcja_sortujaca - wskanik na funkcjącą sortowanie, musi przyjmować dwa parametry: adres początku tablicy (int*) oraz jej rozmiar (int)
|
|
- nazwa - nazwa testowanej funkcji, tylko w celach wypisania
|
|
- output - strumien do ktorego beda zapisane wyniki, domyslnie std::cerr, przy ostatnim uruchomieniu warto nadpisac otwartym strumieniem plikowym, aby sobie zebrac wyniki do pliku
|
|
- dodatkowe_miejsce - liczba dodatkowych elementow tablicy zaalokowanych PRZED poczatkiem tablicy, przykladowo gdy =1, pierwszym indeksem tablicy jest -1, ale dane rozpoczynaja sie od indeksu 0, moze sie przydac do sortowania przez wstawianie z wartownikiem
|
|
*/
|
|
void eksperyment(void(*funkcja_sortujaca)(int*, int), const std::string& nazwa, std::ostream& output = std::cerr, int dodatkowe_miejsce = 0)
|
|
{
|
|
//ustawienia
|
|
const double limit_czasu = 25.0; //sekund
|
|
const int powtorzen = 3;
|
|
const int rozmiar_poczatkowy = 1 << 10;
|
|
/////////////////////////////////////////
|
|
const int szerokosc = 100;
|
|
int gwiazdek = szerokosc - nazwa.length() - 2;
|
|
if (gwiazdek < 0)
|
|
gwiazdek = 0;
|
|
int i = 0;
|
|
output << " ";
|
|
for (; i < gwiazdek / 2; ++i)
|
|
output << '*';
|
|
output << " " << nazwa << " ";
|
|
for (; i < gwiazdek; ++i)
|
|
output << '*';
|
|
output << "\n\n";
|
|
output.flush();
|
|
|
|
output << std::setw(9) << "N";
|
|
output << std::setw(1) << "";
|
|
for (int nr = 0; nr < powtorzen; ++nr)
|
|
output << std::setw(9) << nr + 1 << " ";
|
|
output << std::setw(12) << "średnia" << " ";
|
|
output << "\n";
|
|
for (int rozmiar = rozmiar_poczatkowy; ; rozmiar *= 2)
|
|
{
|
|
output << std::setw(9) << rozmiar << ": ";
|
|
output.flush();
|
|
int* pamiec = new int[dodatkowe_miejsce + rozmiar];
|
|
int* tablica = pamiec + dodatkowe_miejsce;
|
|
double czas = 0.0;
|
|
|
|
int* pattern = new int[rozmiar];
|
|
|
|
|
|
for (int nr = 0; nr < powtorzen; ++nr)
|
|
{
|
|
wypelnij(tablica, rozmiar);
|
|
for (int i = 0; i < rozmiar; ++i)
|
|
pattern[i] = tablica[i];
|
|
std::sort(pattern, pattern + rozmiar);
|
|
double c = mierz_czas(tablica, rozmiar, funkcja_sortujaca);
|
|
if (!jest_posortowane(tablica, rozmiar))
|
|
{
|
|
output << "Tablica nieposortowana!!\n";
|
|
if (&output != &std::cerr)
|
|
std::cerr << "Tablica nieposortowana!!\n";
|
|
return;
|
|
}
|
|
if (!std::equal(pattern, pattern + rozmiar, tablica, tablica + rozmiar))
|
|
{
|
|
output << "Tablica zawiera inne wartosci niz powinna!!\n";
|
|
if (&output != &std::cerr)
|
|
std::cerr << "Tablica zawiera inne wartosci niz powinna!!\n";
|
|
return;
|
|
}
|
|
czas += c;
|
|
output.precision(6);
|
|
output << std::fixed << c << " ";
|
|
output.flush();
|
|
}
|
|
czas /= powtorzen;
|
|
output << std::setw(12) << std::fixed << czas << "\n";
|
|
output.flush();
|
|
delete[] pamiec;
|
|
delete[] pattern;
|
|
if (czas > limit_czasu)
|
|
break;
|
|
}
|
|
output << "\n";
|
|
output.flush();
|
|
}
|
|
|
|
void wypelnij_posortowane_dane_wejsciowe(int* tablica, int rozmiar, int min = 0, int max = std::numeric_limits<int>::max())
|
|
{
|
|
for (int i = 0; i < rozmiar; ++i)
|
|
tablica[i] = i;
|
|
}
|
|
|
|
/*
|
|
|
|
parametry:
|
|
- funkcja_sortujaca - wskanik na funkcjącą sortowanie, musi przyjmować dwa parametry: adres początku tablicy (int*) oraz jej rozmiar (int)
|
|
- nazwa - nazwa testowanej funkcji, tylko w celach wypisania
|
|
- output - strumien do ktorego beda zapisane wyniki, domyslnie std::cerr, przy ostatnim uruchomieniu warto nadpisac otwartym strumieniem plikowym, aby sobie zebrac wyniki do pliku
|
|
- dodatkowe_miejsce - liczba dodatkowych elementow tablicy zaalokowanych PRZED poczatkiem tablicy, przykladowo gdy =1, pierwszym indeksem tablicy jest -1, ale dane rozpoczynaja sie od indeksu 0, moze sie przydac do sortowania przez wstawianie z wartownikiem
|
|
*/
|
|
void eksperyment_posortowane_dane_wejsciowe(void(*funkcja_sortujaca)(int*, int), const std::string& nazwa, std::ostream& output = std::cerr, int dodatkowe_miejsce = 0)
|
|
{
|
|
//ustawienia
|
|
const double limit_czasu = 5.0; //sekund
|
|
const int powtorzen = 3;
|
|
const int rozmiar_poczatkowy = 1 << 10;
|
|
/////////////////////////////////////////
|
|
const int szerokosc = 100;
|
|
int gwiazdek = szerokosc - nazwa.length() - 2;
|
|
if (gwiazdek < 0)
|
|
gwiazdek = 0;
|
|
int i = 0;
|
|
output << " ";
|
|
for (; i < gwiazdek / 2; ++i)
|
|
output << '*';
|
|
output << " " << nazwa << " ";
|
|
for (; i < gwiazdek; ++i)
|
|
output << '*';
|
|
output << "\n\n";
|
|
output.flush();
|
|
|
|
output << std::setw(9) << "N";
|
|
output << std::setw(1) << "";
|
|
for (int nr = 0; nr < powtorzen; ++nr)
|
|
output << std::setw(9) << nr + 1 << " ";
|
|
output << std::setw(12) << "średna" << " ";
|
|
output << "\n";
|
|
for (int rozmiar = rozmiar_poczatkowy; ; rozmiar *= 2)
|
|
{
|
|
output << std::setw(9) << rozmiar << ": ";
|
|
output.flush();
|
|
int* pamiec = new int[dodatkowe_miejsce + rozmiar];
|
|
int* tablica = pamiec + dodatkowe_miejsce;
|
|
double czas = 0.0;
|
|
|
|
int* pattern = new int[rozmiar];
|
|
|
|
|
|
for (int nr = 0; nr < powtorzen; ++nr)
|
|
{
|
|
wypelnij(tablica, rozmiar);
|
|
for (int i = 0; i < rozmiar; ++i)
|
|
pattern[i] = tablica[i];
|
|
std::sort(pattern, pattern + rozmiar);
|
|
double c = mierz_czas(tablica, rozmiar, funkcja_sortujaca);
|
|
if (!jest_posortowane(tablica, rozmiar))
|
|
{
|
|
output << "Tablica nieposortowana!!\n";
|
|
if (&output != &std::cerr)
|
|
std::cerr << "Tablica nieposortowana!!\n";
|
|
return;
|
|
}
|
|
if (!std::equal(pattern, pattern + rozmiar, tablica, tablica + rozmiar))
|
|
{
|
|
output << "Tablica zawiera inne wartosci niz powinna!!\n";
|
|
if (&output != &std::cerr)
|
|
std::cerr << "Tablica zawiera inne wartosci niz powinna!!\n";
|
|
return;
|
|
}
|
|
czas += c;
|
|
output.precision(6);
|
|
output << std::fixed << c << " ";
|
|
output.flush();
|
|
}
|
|
czas /= powtorzen;
|
|
output << std::setw(12) << std::fixed << czas << "\n";
|
|
output.flush();
|
|
delete[] pamiec;
|
|
delete[] pattern;
|
|
if (czas > limit_czasu || rozmiar >= 67108864)
|
|
break;
|
|
}
|
|
output << "\n";
|
|
output.flush();
|
|
}
|
|
|
|
void sortowanie_wybieranie(int* tablica, int rozmiar){
|
|
for (int i = 0; i < rozmiar - 1; i++) {
|
|
int k = i;
|
|
int x = tablica[i];
|
|
for (int ii = i+1; ii < rozmiar; ii++) {
|
|
if (tablica[ii] < x) {
|
|
k = ii;
|
|
x = tablica[ii];
|
|
}
|
|
}
|
|
tablica[k]=tablica[i];
|
|
tablica[i]=x;
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
void sortowanie_wstawianie(int* tablica, int rozmiar){
|
|
for (int i = 1; i < rozmiar; i++) {
|
|
int x = tablica[i];
|
|
int ii = i - 1;
|
|
while ((ii > -1) && (x < tablica[ii])) {
|
|
tablica[ii+1] = tablica[ii];
|
|
ii=ii-1;
|
|
}
|
|
tablica[ii+1] = x;
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
void sortowanie_babelkowe(int* tablica, int rozmiar)
|
|
{
|
|
for(int i = 0; i < rozmiar; i++)
|
|
{
|
|
for (int ii = 1; ii < rozmiar; ii++) {
|
|
if (tablica[ii-1] > tablica[ii]) {
|
|
swap(tablica[ii-1], tablica[ii]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ulepszone_sortowanie_babelkowe(int* tablica, int rozmiar)
|
|
{
|
|
for(int i = 0; i < rozmiar; i++)
|
|
{
|
|
|
|
bool wejscie_do_ifa=false;
|
|
for (int ii = 1; ii < rozmiar-i; ii++) {
|
|
if (tablica[ii-1] > tablica[ii]) {
|
|
swap(tablica[ii-1], tablica[ii]);
|
|
wejscie_do_ifa = true;
|
|
}
|
|
}
|
|
|
|
if (wejscie_do_ifa==false) {break;}
|
|
}
|
|
}
|
|
|
|
|
|
void sortowanie_shella(int* tablica, int rozmiar)
|
|
{
|
|
int h = 1;
|
|
while(h<rozmiar/9){
|
|
h=3*h+1;
|
|
}
|
|
while(h>0){
|
|
for (int i=h; i<rozmiar; i++){
|
|
int x = tablica[i];
|
|
int j = i;
|
|
while ( (j >= h) && ( x< tablica[j-h])){
|
|
tablica[j]=tablica[j-h];
|
|
j=j-h;
|
|
}
|
|
tablica[j]=x;
|
|
}
|
|
h=h/3;
|
|
}
|
|
}
|
|
|
|
void qs(int* tab, int d, int g){
|
|
if (d<g) {
|
|
int t = tab[d];
|
|
int s = d;
|
|
for (int i = d+1; i <= g; i++) {
|
|
if (tab[i]<t) {
|
|
s=s+1;
|
|
swap(tab[s],tab[i]);
|
|
}
|
|
}
|
|
swap(tab[d],tab[s]);
|
|
qs(tab, d, s-1);
|
|
qs(tab, s+1, g);
|
|
}
|
|
}
|
|
|
|
void kopiec_w_dol(int* tablica, int i, int rozmiar_kopca){
|
|
int lewy = ((i+1) * 2)-1;
|
|
int prawy = (i+1) * 2 ;
|
|
int największe;
|
|
if (lewy < rozmiar_kopca && tablica[lewy] > tablica[i]) {
|
|
największe=lewy;
|
|
} else {
|
|
największe=i;
|
|
}
|
|
if (prawy < rozmiar_kopca && tablica[prawy] > tablica[największe]){
|
|
największe=prawy;
|
|
}
|
|
if (największe !=i){
|
|
swap(tablica[i], tablica[największe]);
|
|
kopiec_w_dol(tablica,największe,rozmiar_kopca);
|
|
}
|
|
}
|
|
|
|
void buduj_kopiec(int* tablica, int rozmiar){
|
|
int rozmiar_kopca = rozmiar;
|
|
for (int i = rozmiar/2; i >= 0; i--) {
|
|
kopiec_w_dol(tablica, i, rozmiar_kopca);
|
|
}
|
|
}
|
|
|
|
void sortowanie_kopcowanie(int* tablica, int rozmiar){
|
|
int rozmiar_kopca = rozmiar;
|
|
buduj_kopiec(tablica, rozmiar);
|
|
for (int i = rozmiar-1; i >= 1; i--) {
|
|
swap(tablica[0], tablica[i]);
|
|
rozmiar_kopca--;
|
|
kopiec_w_dol(tablica,0, rozmiar_kopca);
|
|
}
|
|
}
|
|
|
|
void sortowanie_std(int* tablica, int rozmiar){
|
|
std::sort(tablica, tablica + rozmiar);
|
|
}
|
|
|
|
void sortowanie_szybkie(int* tablica, int rozmiar){
|
|
qs(tablica, 0, rozmiar-1);
|
|
}
|
|
|
|
void qs_mod(int* tab, int d, int g){
|
|
if (d<g) {
|
|
if (g-d<20) {
|
|
return;
|
|
}
|
|
int t = tab[d];
|
|
int s = d;
|
|
for (int i = d+1; i <= g; i++) {
|
|
if (tab[i]<t) {
|
|
s=s+1;
|
|
swap(tab[s],tab[i]);
|
|
}
|
|
}
|
|
swap(tab[d],tab[s]);
|
|
qs_mod(tab, d, s-1);
|
|
qs_mod(tab, s+1, g);
|
|
}
|
|
}
|
|
void sortowanie_szybkie_mod(int* tablica, int rozmiar){
|
|
qs_mod(tablica, 0, rozmiar-1);
|
|
sortowanie_wstawianie(tablica, rozmiar);
|
|
}
|
|
|
|
|
|
|
|
int main()
|
|
{
|
|
setlocale(LC_ALL, "");
|
|
std::ofstream wyniki("wyniki.txt");
|
|
std::ostream& output = wyniki;//std::cerr; // Wypisanie do pliku (zamiast na ekran)
|
|
//std::ostream& output = std::cerr; // Wypisanie na ekran
|
|
eksperyment(sortowanie_shella, "Sortowanie shella", output);
|
|
eksperyment(sortowanie_szybkie, "Sortowanie szybkie", output);
|
|
eksperyment(sortowanie_szybkie_mod, "Sortowanie szybkie z modyfikacją", output);
|
|
eksperyment(ulepszone_sortowanie_babelkowe, "Ulepszone sortowanie bąbelkowe", output);
|
|
eksperyment(sortowanie_babelkowe, "Sortowanie bąbelkowe", output);
|
|
eksperyment(sortowanie_wstawianie, "Sortowanie przez proste wstawianie", output);
|
|
eksperyment(sortowanie_wybieranie, "Sortowanie przez proste wybieranie", output);
|
|
eksperyment(sortowanie_kopcowanie, "Sortowanie przez kopcowanie", output);
|
|
eksperyment(sortowanie_std, "Sortowanie std::sort", output);
|
|
return 0;
|
|
}
|