School-Coding-Cpp/sfusi/fshakerSort.cpp

147 lines
3.4 KiB
C++

/*
Nome: Mario
Cognome: Montanari
Classe: 3AIN
Data: 05/05/2025
Funzione di Shaker Sort che ordina direttamente su un file
*/
#include <iostream>
using namespace std;
typedef struct {
int value;
} basetype;
void fshakerSort(FILE * file);
void swapInFile(FILE * file, int i, int j);
void fprint(const char * filename);
int main(void) {
const char * filename = "data.bin";
// Apertura del file
FILE * file = fopen(filename, "r+b");
if (file != NULL) {
fshakerSort(file); // Esegui lo shaker sort
fprint(filename); // Stampa il risultato
fclose(file); // Chiudi il file
} else {
perror("Errore nell'aprire il file");
}
return 0;
}
void fshakerSort(FILE * file) {
// Spostati alla fine del file per ottenere il numero di elementi
fseek(file, 0, SEEK_END);
long n = ftell(file) / sizeof(basetype);
if (n < 2) {
return; // Se il file ha meno di due elementi, non è necessario ordinare
}
rewind(file); // Torna all'inizio del file
int left = 0;
int right = n - 1;
bool swapped = true;
while (left < right && swapped) {
swapped = false;
// Passaggio da sinistra verso destra
for (int i = left; i < right; i++) {
basetype a, b;
// Leggi i due valori da scambiare
fseek(file, i * sizeof(basetype), SEEK_SET);
fread(&a, sizeof(basetype), 1, file);
fseek(file, (i + 1) * sizeof(basetype), SEEK_SET);
fread(&b, sizeof(basetype), 1, file);
if (a.value > b.value) {
swapInFile(file, i, i + 1); // Effettua lo swap se i valori sono nell'ordine sbagliato
swapped = true;
}
}
right--; // Riduci l'area da esaminare
// Passaggio da destra verso sinistra
for (int i = right; i > left; i--) {
basetype a, b;
fseek(file, (i - 1) * sizeof(basetype), SEEK_SET);
fread(&a, sizeof(basetype), 1, file);
fseek(file, i * sizeof(basetype), SEEK_SET);
fread(&b, sizeof(basetype), 1, file);
if (a.value > b.value) {
swapInFile(file, i - 1, i); // Effettua lo swap se i valori sono nell'ordine sbagliato
swapped = true;
}
}
left++; // Espandi l'area da esaminare
}
}
void swapInFile(FILE * file, int i, int j) {
if (i == j) {
return; // Nessun bisogno di fare uno swap se gli indici sono uguali
}
basetype a, b;
// Leggi i valori da scambiare
fseek(file, i * sizeof(basetype), SEEK_SET);
if (fread(&a, sizeof(basetype), 1, file) != 1) {
cout << "Errore di lettura (i)!" << endl;
return;
}
fseek(file, j * sizeof(basetype), SEEK_SET);
if (fread(&b, sizeof(basetype), 1, file) != 1) {
cout << "Errore di lettura (j)!" << endl;
return;
}
// Scrivi i valori scambiati
fseek(file, i * sizeof(basetype), SEEK_SET);
if (fwrite(&b, sizeof(basetype), 1, file) != 1) {
cout << "Errore di scrittura (i)!" << endl;
return;
}
fseek(file, j * sizeof(basetype), SEEK_SET);
if (fwrite(&a, sizeof(basetype), 1, file) != 1) {
cout << "Errore di scrittura (j)!" << endl;
return;
}
}
void fprint(const char * filename) {
FILE * file = fopen(filename, "rb");
if (file != NULL) {
basetype temp;
while (fread(&temp, sizeof(basetype), 1, file) == 1) {
cout << temp.value << " "; // Stampa i valori letti
}
cout << endl;
fclose(file);
} else {
perror("Errore nell'aprire il file per la lettura");
}
}