text: /*
   * sorts.c
   *
   *  Created on: 2. 6. 2019
   *      Author: Adam Bublavy
   */
  
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  
  void swap(void * a, void * b, size_t elementSize) {
  	void * tmp = malloc(elementSize);
  	memcpy(tmp, b, elementSize);
  	memcpy(b, a, elementSize);
  	memcpy(a, tmp, elementSize);
  	free(tmp);
  }
  
  void bubbleSort(void * array, int n, size_t elementSize, int (*compareFunction)(const void *, const void *)) {
  	int iElement = 0, jElement = 0;
  
  	for(int i = 0; i < n - 1; i ++) {
  		for(int j = i + 1; j < n; j ++) {
  			jElement += elementSize;
  
  			if(compareFunction(array + jElement, array + iElement) < 0) {
  				swap(array + jElement, array + iElement, elementSize);
  			}
  		}
  
  		iElement += elementSize;
  		jElement = (i + 1) * elementSize;
  	}
  }
  
  void selectionSort(void * array, int n, size_t elementSize, int (*compareFunction)(const void *, const void *)) {
  	int iElement = 0, jElement = 0, minElement = 0;
  
  	for(int i = 0; i < n - 1; i ++) {
  		minElement = i * elementSize;
  
  		for(int j = i + 1; j < n; j ++) {
  			jElement += elementSize;
  
  			if(compareFunction(array + jElement, array + minElement) < 0) minElement = j * elementSize;
  		}
  
  		if(minElement != i / elementSize) swap(array + iElement, array + minElement, elementSize);
  
  		iElement += elementSize;
  		jElement = (i + 1) * elementSize;
  	}
  }
  
  void insertionSort(void * array, int n, size_t elementSize, int (*compareFunction)(const void *, const void *)) {
  	void * currentValue = malloc(elementSize);
  
  	int j, jElement = 0, nextJElement = 0;
  
  	for(int i = 0; i < n; i ++) {
  		j = i - 1;
  		jElement = j * elementSize;
  		nextJElement = jElement + elementSize;
  
  		memcpy(currentValue, array + i * elementSize, elementSize);
  
  		while(j >= 0 && compareFunction(array + jElement, currentValue) > 0) {
  			memcpy(array + nextJElement, array + jElement, elementSize);
  
  			j --;
  			jElement -= elementSize;
  			nextJElement -= elementSize;
  		}
  
  		memcpy(array + nextJElement, currentValue, elementSize);
  	}
  
  	free(currentValue);
  }
  
  void merge(void * array, int n, size_t elementSize, int (*compareFunction)(const void *, const void *)) {
  	int amountOfElementsLeft = n / 2;
  	int amountOfElementsRight = n - n / 2;
  
  	void * leftTemp = malloc(elementSize * amountOfElementsLeft);
  	void * rightTemp = malloc(elementSize * amountOfElementsRight);
  
  	memcpy(leftTemp, array, amountOfElementsLeft * elementSize);
  	memcpy(rightTemp, array + amountOfElementsLeft * elementSize, amountOfElementsRight * elementSize);
  
  	int leftTempIndex = 0, rightTempIndex = 0, arrayIndex = 0;
  	int leftTempElement = 0, rightTempElement = 0, arrayElement = 0;
  
  	while(leftTempIndex < amountOfElementsLeft && rightTempIndex < amountOfElementsRight) {
  		if(compareFunction(leftTemp + leftTempElement, rightTemp + rightTempElement) <= 0) {
  			memcpy(array + arrayElement, leftTemp + leftTempElement, elementSize);
  			leftTempIndex ++;
  			leftTempElement += elementSize;
  		}
  		else {
  			memcpy(array + arrayElement, rightTemp + rightTempElement, elementSize);
  			rightTempIndex ++;
  			rightTempElement += elementSize;
  		}
  
  		arrayIndex ++;
  		arrayElement += elementSize;
  	}
  
  	while(leftTempIndex < amountOfElementsLeft) {
  		memcpy(array + arrayElement, leftTemp + leftTempElement, elementSize);
  		arrayIndex ++, leftTempIndex ++;
  		arrayElement += elementSize, leftTempElement += elementSize;
  	}
  
  	while(rightTempIndex < amountOfElementsRight) {
  		memcpy(array + arrayElement, rightTemp + rightTempElement, elementSize);
  		arrayIndex ++, rightTempIndex ++;
  		arrayElement += elementSize, rightTempElement += elementSize;
  	}
  
  	free(leftTemp);
  	free(rightTemp);
  }
  
  void mergeSort(void * array, int n, size_t elementSize, int (*compareFunction)(const void *, const void *)) {
  	if(n <= 1) return;
  
  	int amountOfElementsLeft = n / 2;
  	int amountOfElementsRight = n - amountOfElementsLeft;
  
  	mergeSort(array, amountOfElementsLeft, elementSize, compareFunction);
  	mergeSort(array + amountOfElementsLeft * elementSize, amountOfElementsRight, elementSize, compareFunction);
  	merge(array, n, elementSize, compareFunction);
  }
  