Untitled
unknown
plain_text
10 months ago
14 kB
3
Indexable
#include <iostream>
#include <string>
using namespace std;
struct simple_object {
string word;
double key;
friend ostream& operator<<(ostream& os, simple_object so);
};
int simple_object_comparator(simple_object so1, simple_object so2) {
if (so1.key == so2.key)
return 0;
else if (so1.key < so2.key)
return -1;
else if (so1.key > so2.key)
return 1;
}
ostream& operator<<(ostream& os, simple_object so) { // CHUJ WIE
string key = to_string(so.key);
key.erase(key.find_last_not_of('0') + 1, string::npos);
key.erase(key.find_last_not_of('.') + 1, string::npos);
os << "Word: " + so.word + "; key: " + key + "\n";
return os;
}
int int_cmp(int i1, int i2) { // jest potrzebny do heapsorta jako argument
if (i1 == i2)
return 0;
else if (i1 < i2)
return -1;
else if (i1 > i2)
return 1;
}
// heapSort
enum mode { BOTTOM_UP, TOP_DOWN };
template <typename T>
struct HeapSort {
int size;
T* heap_array;
HeapSort(T* array, int n, int (*func)(T, T), bool mode = BOTTOM_UP) { // konstruktor (tablica, rozmiar, komparator, tryb)
heap_array = array; // uznajemy ze ta tablica to kopiec i dopiero ja bedziemy naprawiac
if (mode == BOTTOM_UP) { // w razie czego sprawdzic czy nie pomylil krystian nazw !!!
size = 0; // uznajemy ze tablica jest pusta mimo ze tak naprawde jest pelna
for (int i = 0; i < n; i++) { // przy kazdej iteracji zwiekszamy (uznajemy ze jest o jeden wiekszy jest jej rozmiar)
size++;
heapUp(size, func); // tak jakby odkrywamy sobie po elemencie i robimy heap up
}
}
else if (mode == TOP_DOWN) {
size = n; // uznajemy ze jest pelna tablica (widzimy ja cala)
for (int i = size / 2; i > -1; i--) { // idziemy od size/2 (taka zasada w heapie, bo ona nam pozwala na pominiecie liscie (ostatniego rzedu elementow))
heapDown(i, func);
}
}
sort(size, func); // konstruktor u mnie odrazu sortuje jakby sie przyprul skurwol zamaist tworzyc kopca i uzyc funkcje to dziala odrazu razem z tworzeniem kopca bo tak mi bylo wygodniej
}
// po naprawieniu kopca, idziemy od ostatniego elementu w tyl (przedostatni itd) oraz zawsze zamieniamy ostatni n-1 z pierwszym, zmniejszamy size (czyli potem ostatnim bedzie ten co chwile przed tym był przedostatnim) i robimy heap down, w zwiazku z czym po posortowaniu na samym dole (w lisciach kopca) bedziemy mieli najwieksze elementy
void sort(int& size, int (*func)(T, T)) {
for (int i = size - 1; i > 0; i--) {
swap(heap_array[i], heap_array[0]); // jak cos to pomoc z neta (zawsze raczej bedzie wygldadac tak samo)
size--;
heapDown(0, func);
}
}
T get(int index) {
if (index < size) {
return heap_array[index];
}
}
int parent(int i) {
i++;
return (i >> 1) - 1;
}
int left_child(int i) {
i++;
return (i << 1) - 1;
}
int right_child(int i) {
i++;
return (i << 1);
}
void heapUp(int el_index, int (*func)(T, T)) {
if (func(heap_array[el_index], heap_array[parent(el_index)]) == 1 && el_index > 0) {
T tmp = heap_array[parent(el_index)];
heap_array[parent(el_index)] = heap_array[el_index];
heap_array[el_index] = tmp;
heapUp(parent(el_index), func);
}
}
string str(string(*func)(T), int k = -1) {
return heap_array->str(func, k);
}
void heapDown(int el_index, int (*func)(T, T)) {
int l_child_index = left_child(el_index);
int r_child_index = right_child(el_index);
int largest;
if (l_child_index < size && func(heap_array[l_child_index], heap_array[el_index]) == 1)
largest = l_child_index;
else
largest = el_index;
if (r_child_index < size && func(heap_array[r_child_index], heap_array[largest]) == 1)
largest = r_child_index;
if (el_index != largest) {
swap(heap_array[el_index], heap_array[largest]);
heapDown(largest, func);
}
}
};
// count sort -> wykład 1:1, tak ma po prostu byc kazdy probably bedzie mial to samo
void countSort(int* arr, int size, int max) {
int* array = new int[max] { 0 };
for (int i = 0; i < size; i++)
array[arr[i]]++;
int i = 0;
for (int j = 0; j < max; j++) {
while (array[j] > 0) {
array[j]--;
arr[i++] = j;
}
}
delete[] array; // nw czy zadziała
}
// BucketSort
template <typename T>
struct Node {
struct Node<T>* prev = nullptr;
T data;
struct Node<T>* next = nullptr;
};
template <typename T>
struct LinkedList {
struct Node<T>* head = nullptr;
struct Node<T>* tail = nullptr;
int size = 0;
T get(int i) {
Node<T>* n = head;
for (int j = 0; j < i; j++) {
n = n->next;
}
return n->data;
}
void pushFront(T data) {
// tworzenie węzła
Node<T>* n = new Node<T>();
n->data = data;
n->next = head;
// jeśli nie został wcześniej dodany żaden element
if (head != nullptr) {
head->prev = n;
}
else {
tail = n;
head = n;
}
head = n;
// zwiększenie informacji o ilości elementów znajdujących się w liście
size++;
}
void sortInsert(T data, int (*func)(T, T)) {
if (head == nullptr || func(head->data, data) == 1 || func(head->data, data) == 0) {
pushFront(data);
return;
}
else if (func(tail->data, data) == -1 || func(tail->data, data) == 0) {
pushBack(data);
return;
}
Node<T>* current = head;
while (current->next != nullptr && func(current->next->data, data) == -1) {
current = current->next;
}
Node<T>* newNode = new Node<T>();
newNode->data = data;
newNode->next = current->next;
current->next = newNode;
size++;
}
void pushBack(T data) {
// tworzenie węzła
Node<T>* n = new Node<T>();
n->data = data;
n->prev = tail;
// jeśli nie został wcześniej dodany żaden element
if (tail != nullptr) {
tail->next = n;
}
else {
head = n;
tail = n;
}
tail = n;
// zwiększenie informacji o ilości elementów znajdujących się w liście
size++;
}
void clear() {
Node<T>* n = head;
Node<T>* lastFound = nullptr;
if (head == nullptr) {
cout << "Lista nie zawiera żadnych elementów";
return;
}
while (true) {
lastFound = n;
n = n->next;
if (n == nullptr)
break;
delete n->prev;
size--;
}
delete lastFound;
// ustawienie tail i head na nullptr
head = tail = nullptr;
}
int getSize() {
return size;
}
};
// BucketSort dla int
void bucketSort(int* arr, int size, int max) {
int buckets = size;
int sep = ceil(max / (float)buckets); // może z internetu, na stronie geeksforgeeks byl wytlumaczone chyba, tylko trzeba zjechac na dol strony i pod kodem bedzie podział dla intow zamiast dla float chyba
LinkedList<int>* array = new LinkedList<int>[buckets];
int index;
for (int i = 0; i < size; i++) {
index = arr[i] / sep;
array[index].sortInsert(arr[i], int_cmp);
}
for (int i = 0; i < size; i++)
arr[i] = 0;
int j = 0;
for (int i = 0; i < buckets; i++) {
int list_size = array[i].getSize();
for (int k = 0; k < list_size; k++) {
arr[j++] = array[i].get(k);
}
if (array[i].getSize())
array[i].clear();
}
delete[] array;
}
// BucketSort dla reszty (to nie jest sortowanie w miejscu, z tych 3 tylkko heapsort jest)
template <typename T>
void bucketSort(T* arr, int size, double max, double (*func_k)(T), int (*func_cmp)(T, T)) {
int buckets = size;
// jest kubełkow tyle ile jest elementow w tablicy, zeby przy rozkladzie jakims jednostajnym wyszlo tak ze do kubelka trafi jedna liczba czyli nie bedzie trzeba sortowac kubelka (sortowanie w srodku ma byc jak najkrotsze, a w kubelku chcemy zeby bylo jak najmniej elementow)
// najlepsze n+k, a najgorszy przypadek n^2
LinkedList<T>* array = new LinkedList<T>[buckets];
int index;
double key;
for (int i = 0; i < size; i++) {
key = func_k(arr[i]); // funkcja ktora bierze klucz z obiektu
index = key / (max / buckets); // przydzielenie wartosci indeksu kubelka do ktorego ma trafic element z tablicy (kazdy kubelek to lista, a jak lista jednoelementowa to nie ma co sortowac prosciutto crudo)
array[index].sortInsert(arr[i], func_cmp); // 1 sposob -> powkladac wszystko i posortowac, 2 sposob -> odrazu sie wklada do kubelka w miejscu w ktorym powinno byc (tutaj uzywamy 2 sposobu)
} // po tym mam wszystkie juz elementy w kubelkach i kubelki sa posortowane
// caly ten for odpowiada za wyciaganie z kubelkow do tablicy jako posortowane elementy
int j = 0;
for (int i = 0; i < buckets; i++) { // mamy pierwszy kubelek, w nim lista i iterujemy po kubelkach i z kazdego kubelka wyciagamy te elementy
int list_size = array[i].getSize();
for (int k = 0; k < list_size; k++) {
arr[j++] = array[i].get(k); // dodawanie posortowanych elementow z kubelka do tablicy
}
if (list_size != 0)
array[i].clear(); // czyszczenie listy
}
delete[] array; // zwalniamy pamiec
}
double simple_object_key(simple_object so) {
return so.key;
}
// int main()
// {
// srand(time(NULL));
// //int tablica[30];
// //for (int i = 0; i < 30; i++)
// // tablica[i] = rand() % 100;
// //cout << "Talibca: \n";
// //for (int i = 0; i < 30; i++) {
// // cout << tablica[i] << ", ";
// //}
// //cout << "\n";
// //countSort(tablica, 30, 100);
// //bucketSort(tablica, 30, 100);
// // HeapSort<int>* bh = new HeapSort<int>(tablica, 30, int_cmp, BOTTOM_UP);
// //for (int i = 0; i < 30; i++)
// // cout << tablica[i] << ", ";
// simple_object so_tab[]{ {"marcin9", 10.}, {"marcin1", 0.87}, {"marcin3", 1.87}, {"marcin0", 0.00568}, {"marcin4", 2.33},{"marcin10", 10.008}, {"marcin6", 5.18}, {"marcin2", 1.07}, {"marcin5", 3.33}, {"marcin8", 9.33}, {"marcin7", 8.1} };
// bucketSort(so_tab, 11, 11, simple_object_key, simple_object_comparator);
// for (int i = 0; i < 11; i++)
// cout << so_tab[i];
// }
int main()
{
const int MAX_ORDER = 7;
const int m = (int)pow(10, 7);
for (int o = 1; o <= MAX_ORDER; o++) {
const int n = (int)pow(10, o);
int* array1 = new int[n];
for (int i = 0; i < n; i++) {
array1[i] = rand() % m;
}
int* array2 = new int[n];
int* array3 = new int[n];
memcpy(array2, array1, n * sizeof(int));
memcpy(array3, array1, n * sizeof(int));
clock_t t1 = clock();
countSort(array1, n, m);
clock_t t2 = clock();
cout << "\nCounting sort czas: " << (t2 - (double)t1) / CLOCKS_PER_SEC << endl;
for (int i = 0; i < 10; i++) { // pierwsze 10 elementow
cout << array1[i] << ", ";
}
t1 = clock();
HeapSort<int>* bh = new HeapSort<int>(array2, n, int_cmp, BOTTOM_UP);
t2 = clock();
cout << "\nHeap sort czas: " << (t2 - (double)t1) / CLOCKS_PER_SEC << endl;
for (int i = 0; i < 10; i++) { // pierwsze 10 elementow
cout << array2[i] << ", ";
}
t1 = clock();
bucketSort(array3, n, m);
t2 = clock();
cout << "\nBucket sort czas: " << (t2 - (double)t1) / CLOCKS_PER_SEC << endl;
for (int i = 0; i < 10; i++) { // pierwsze 10 elementow
cout << array3[i] << ", ";
}
delete[] array1;
delete[] array2;
delete[] array3;
}
}
//int main() {
// const int MAX_ORDER = 7; // m a k s y m a l n y rzad w i e l k o s c i s o r t o w a n y c h danych
// const double m_double = (double)pow(2, 30); // m i a n o w n i k przy u s t a l a n i u losowej liczby
//
// for (int o = 1; o <= MAX_ORDER; o++) {
// const int n = (int)pow(10, o);
//
// simple_object* array1 = new simple_object[n];
//
// for (int i = 0; i < n; i++) {
// array1[i].key = rand();
// array1[i].word = "hjkhkjhkj"; // obojetnie jakie bo i tak nie bierze udzial w niczym
// }
//
// clock_t t1 = clock();
// HeapSort<simple_object>* bh = new HeapSort<simple_object>(array1, n, simple_object_comparator, TOP_DOWN);
// clock_t t2 = clock();
//
// cout << "\nHeap sort czas: " << (t2 - (double)t1) / CLOCKS_PER_SEC << endl;
// for (int i = 0; i < 10; i++)
// cout << array1[i] << ", ";
//
// delete[] array1;
// delete[] bh;
//
// // DZIAŁA HEAP SORT NIE DZIAŁA BUCKET SORT NIE WIADOMO CZEMU
//
// }
//}
Editor is loading...
Leave a Comment