sav

Sorting Algorithms Visualized
Index Commits Files Refs README LICENSE
commit 04b1eef81c8358648bea2c5b6ca01f5643471e0d
parent 0205dc18cddcfaa5f1647773f0977e639c268aff
Author: klewer-martin <martin.cachari@gmail.com>
Date:   Sun, 24 Apr 2022 01:44:58 -0300

Added heap sort algorithm

Heap sort algorithm added, plus other fixes

Diffstat:
Mdrw.c | 12++++++------
Mdrw.h | 18++++++++++--------
Mmain.c | 18++++++++++--------
Msav.h | 1+
Msort.c | 88++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
Msort.h | 3+++
6 files changed, 111 insertions(+), 29 deletions(-)
diff --git a/drw.c b/drw.c
@@ -47,29 +47,29 @@ void drw_status_bar(Drw *drw, SAV *sav) {
     /* TODO: create a function which fetchs the status text to be drawn based on the status */
     if(sav->status == WELCOME) {
         snprintf(drw->bar_text, drw->bar_text_len - 2,
-                "  Welcome to sorting algorithms visualized  [%s sort]  press SPACE to start sorting",
+                "  Welcome to sorting algorithms visualized  [%s]  press SPACE to start sorting",
                 algo_sel_str[sav->sort_algo]);
     }
     else if(sav->status == START) {
         snprintf(drw->bar_text, drw->bar_text_len - 2,
-                "  %-8s  [%s sort]   press SPACE to start sorting", sort_status_str[OK],
+                "  %-8s  [%s]   press SPACE to start sorting", sort_status_str[OK],
                 algo_sel_str[sav->sort_algo]);
     }
     else if(sav->status == RUN) {
         if(sav->sort_status == PAUSE)
             snprintf(drw->bar_text, drw->bar_text_len - 2,
-                    "  %-8s  [%s sort]   L: %ld, C: %ld, S: %ld   Press SPACE to resume", sort_status_str[sav->sort_status],
+                    "  %-8s  [%s]   L: %ld, C: %ld, S: %ld   Press SPACE to resume", sort_status_str[sav->sort_status],
                     algo_sel_str[sav->sort_algo], sav->arr->len, sav->cmps,
                     sav->swps);
         else if(sav->sort_status == SORTED)
             snprintf(drw->bar_text, drw->bar_text_len - 2,
-                    "  %-8s  [%s sort]   L: %ld, C: %ld, S: %ld, done in %lds, extra storage used: %ld Bytes",
+                    "  %-8s  [%s]   L: %ld, C: %ld, S: %ld, done in %lds, extra storage used: %ld Bytes",
                     sort_status_str[sav->sort_status],
                     algo_sel_str[sav->sort_algo],
                     sav->arr->len, sav->cmps, sav->swps, (sav->tf - sav->ti), sav->B_used);
         else if(sav->sort_status == RUN)
             snprintf(drw->bar_text, drw->bar_text_len - 2,
-                    "  %-8s  [%s sort]   L: %ld, C: %ld, S: %ld", sort_status_str[sav->sort_status],
+                    "  %-8s  [%s]   L: %ld, C: %ld, S: %ld", sort_status_str[sav->sort_status],
                     algo_sel_str[sav->sort_algo], sav->arr->len, sav->cmps,
                     sav->swps);
     }
@@ -141,7 +141,7 @@ status_t Drw_new(Drw **drw) {
     {
         int w_text, h_text;
         TTF_SizeText(font,
-                "SORTED [XXXXXXXXXXs sort] done in XXX.Xs, L: XXXXX,\
+                "SORTED [XXXXXXXXXXXXXXXXXXXXX] done in XXX.Xs, L: XXXXX,\
                 C: XXXXXX, S: XXXXXX, I: XXXXXX, storage used: XXXXXX Bytes",
                 &w_text, &h_text);
 
diff --git a/drw.h b/drw.h
@@ -44,14 +44,16 @@ typedef struct {
     char *bar_text;
 } Drw;
 
-static char * const algo_sel_str[ALGORITHMS_COUNT] = {
-    "bubble",
-    "improved bubble",
-    "insertion",
-    "merge",
-    "quick",
-    "shell",
-    "selection"
+static char * const algo_sel_str[ALGORITHMS_COUNT + 1] = {
+    "bubble sort",
+    "improved bubble sort",
+    "insertion sort",
+    "merge sort",
+    "quick sort",
+    "shell sort",
+    "selection sort",
+    "heap sort",
+    "sort not set"
 };
 
 static char * const sort_status_str[STATUS_MAX] = {
diff --git a/main.c b/main.c
@@ -1,5 +1,6 @@
 #include <stdio.h>
 #include <pthread.h>
+#include <assert.h>
 
 #include "sav.h"
 #include "drw.h"
@@ -23,16 +24,16 @@ static void (*sort_handler[ALGORITHMS_COUNT])(SAV *) = {
     &merge_sort_wrapper,
     &quick_sort_wrapper,
     &shell_sort,
-    &selection_sort
+    &selection_sort,
+    &heap_sort
 };
 
 void *routine_wrapper(void *arg) {
     SAV *sav = (SAV *)arg;
 
-    if(sav->sort_algo == ALGORITHMS_COUNT) {
-        fprintf(stderr, "ERROR: \"sort_algo\" not set. exiting\n");
-        sav->status = STOP;
-    } else sort_handler[sav->sort_algo](sav);
+    assert((sav->sort_algo != ALGORITHMS_COUNT) && "Default sorting algorithm not set");
+
+    sort_handler[sav->sort_algo](sav);
 
     return NULL;
 }
@@ -48,8 +49,8 @@ void sort_selector(SAV *sav) {
 /* TODO: Support sound */
 
 int main (void) {
-    SAV *sav;
-    Drw *drw;
+    SAV *sav = NULL;
+    Drw *drw = NULL;
     time_t tic, toc;
 
     pthread_t p1 = 0;
@@ -62,7 +63,7 @@ int main (void) {
     shuffle(sav->arr);
 
     /* selecting the sorting algorithm */
-    sav->sort_algo = QUICK_SORT;
+    sav->sort_algo = SELECTION_SORT;
 
     sav->status = WELCOME;
     sav->sort_status = PAUSE;
@@ -77,6 +78,7 @@ int main (void) {
 
         drw_array_graph(drw, sav);
         drw_status_bar(drw, sav);
+
         SDL_RenderPresent(drw->rend);
 
         /* Print welcome message only on startup */
diff --git a/sav.h b/sav.h
@@ -18,6 +18,7 @@ typedef enum {
     QUICK_SORT,
     SHELL_SORT,
     SELECTION_SORT,
+    HEAP_SORT,
     ALGORITHMS_COUNT
 } sort_t;
 
diff --git a/sort.c b/sort.c
@@ -7,7 +7,7 @@
 void set_sort_speed(SAV *sav, size_t new_value) {
     if(sav == NULL) return;
 
-    if((new_value > 0) && (new_value < SORT_DELAY_MAX)) {
+    if((new_value > 0) && (new_value <= SORT_DELAY_MAX)) {
         printf("INFO: Updating sort_delay to: %ld\n", new_value);
         sav->sort_delay = new_value;
     }
@@ -143,19 +143,27 @@ void merge(SAV *sav, int low, int middle, int high) {
     for(i = low, j = 0; i < middle; i++, j++)
         B[j] = sav->arr->v[i];
 
-    /* C middle high part of the array */
+    /* C middle high */
     for(i = middle, j = 0; i < high; i++, j++)
         C[j] = sav->arr->v[i];
 
-    /* merge B1 and C1 in order */
+    /* merge B and C in order */
     for(k = low, i = j = 0; (k < high) && (i < n1) && (j < n2); k++) {
-        if(B[i] <= C[j]) sav->arr->v[k] = B[i++];
-        else sav->arr->v[k] = C[j++];
+        if(B[i] <= C[j]) {
+            sav->arr->v[k] = B[i++];
+            sav->cmps += 1;
+        }
+        else {
+            sav->cmps += 1;
+            sav->arr->v[k] = C[j++];
+        }
 
         sav->sel = (k + 1);
         sav->cmps += 1;
         sav->its += 1;
 
+        /* double delay; to match speed of other algorithms */
+        if(sort_delay(sav) == STOP) return;
         if(sort_delay(sav) == STOP) return;
         if(sort_pause(sav) == STOP) return;
     }
@@ -179,6 +187,8 @@ void merge_sort(SAV *sav, int low, int high) {
 
         /* merge both arrays ordered */
         merge(sav, low, middle, high);
+
+        sav->cmps += 1;
     }
 }
 
@@ -208,6 +218,7 @@ void quick_sort_partition(SAV *sav, int low, int *middle, int high) {
         sav->cmp = j;
 
         if(sort_delay(sav) == STOP) return;
+        if(sort_delay(sav) == STOP) return;
         if(sort_pause(sav) == STOP) return;
     }
 
@@ -260,7 +271,6 @@ void shell_sort(SAV *sav) {
             }
             sav->arr->v[j] = temp;
             sav->swps += 1;
-            sav->cmps += 1;
         }
     }
     sav->tf = time(NULL);
@@ -282,7 +292,8 @@ void selection_sort(SAV *sav)
         sav->sel = i;
         for (j = i + 1; j < sav->arr->len; j++) {
             if (sav->arr->v[j] < sav->arr->v[min]) min = j;
-            sav->cmp = min;
+            sav->cmps += 1;
+            sav->cmp = j;
             if(sort_delay(sav) == STOP) return;
             if(sort_pause(sav) == STOP) return;
         }
@@ -290,8 +301,71 @@ void selection_sort(SAV *sav)
         if(sort_delay(sav) == STOP) return;
         if(sort_pause(sav) == STOP) return;
         swap(&sav->arr->v[i], &sav->arr->v[min]);
+        sav->swps += 1;
     }
 
     sav->tf = time(NULL);
     if(sav->sort_status != STOP) sav->sort_status = SORTED;
 }
+
+
+/* build max_heap */
+void heapify(SAV *sav, int len, int i) {
+    /* Find largest among root, left child and right child */
+    int root = i;
+    int child_left = 2 * i + 1;
+    int child_right = 2 * i + 2;
+
+    sav->cmp = child_left;
+    sav->cmps += 1;
+    if((child_left < len) && (sav->arr->v[child_left] > sav->arr->v[root]))
+        root = child_left;
+
+    sav->cmp = child_right;
+    sav->cmps += 1;
+    if((child_right < len) && (sav->arr->v[child_right] > sav->arr->v[root]))
+        root = child_right;
+
+    /* Swap and continue heapifying if root is not root */
+    sav->cmps += 1;
+    if(root != i) {
+        sav->swps += 1;
+        swap(&(sav->arr->v[i]), &sav->arr->v[root]);
+        heapify(sav, len, root);
+    }
+
+    if(sort_delay(sav) == STOP) return;
+    if(sort_pause(sav) == STOP) return;
+}
+
+/* Main function to do heap sort */
+void heap_sort(SAV *sav) {
+    int i;
+    if(sav == NULL) return;
+
+    sav->ti = time(NULL);
+
+    /* Build max heap */
+    for (i = ((sav->arr->len / 2) - 1); i >= 0; i--) {
+        heapify(sav, sav->arr->len, i);
+    }
+
+    /* Heap sort */
+    for (i = (sav->arr->len - 1); i >= 0; i--) {
+        /* The root element gets swapped with the last one, then gets ignored */
+        sav->sel = i;
+
+        sav->swps += 1;
+        swap(&sav->arr->v[0], &sav->arr->v[i]);
+
+        if(sort_delay(sav) == STOP) return;
+        if(sort_pause(sav) == STOP) return;
+
+        /* Heapify root element to get highest element at root again */
+        heapify(sav, i, 0);
+    }
+
+    if(sav->sort_status != STOP) sav->sort_status = SORTED;
+    sav->sel = sav->cmp = ARR_MAX + 1;
+    sav->tf = time(NULL);
+}
diff --git a/sort.h b/sort.h
@@ -26,4 +26,7 @@ void quick_sort_partition(SAV *sav, int low, int *middle, int high);
 void shell_sort(SAV *sav);
 void selection_sort(SAV *sav);
 
+void heap_sort(SAV *sav);
+void heapify(SAV *sav, int len, int i);
+
 #endif // __SORT_H__