#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
struct DataWrapper
{
char* pRawData;
int len;
DataWrapper(char* pRawData, int len)
{
this->pRawData = pRawData;
this->len = len;
}
};
struct Element
{
DataWrapper* data;
Element* next;
Element()
{
this->data = NULL;
this->next = NULL;
}
};
struct LinkedList
{
Element* head;
Element* tail;
int len;
LinkedList()
{
this->head = NULL;
this->tail = NULL;
this->len = 0;
}
void addToHead(Element* element)
{
if (this->len == 0) {
element->next = NULL;
this->head = element;
this->tail = element;
this->len++;
return;
}
element->next = this->head;
this->head = element;
this->len++;
}
void addToTail(Element* element)
{
element->next = NULL;
if (this->len == 0) {
this->head = element;
this->tail = element;
this->len++;
return;
}
this->tail->next = element;
this->tail = element;
this->len++;
}
};
int COMPARE_ELEMENTS_COUNT = 0;
int CompareElements(Element* e1, Element* e2)
{
COMPARE_ELEMENTS_COUNT++;
int res = memcmp(e1->data->pRawData, e2->data->pRawData, (e1->data->len < e2->data->len ? e1->data->len : e2->data->len));
if (res == 0) {
return (e1->data->len - e2->data->len);
}
return res;
}
void performMerge(LinkedList** buffer, int toIndex, int fromIndex)
{
Element* e1 = buffer[toIndex]->head;
Element* e2 = buffer[fromIndex]->head;
Element* prev = NULL;
Element* tmp = NULL;
// [3, 4], [2, 9]
if (e1 != NULL && e2 != NULL) {
if (CompareElements(e1, e2) > 0) {
buffer[toIndex]->head = e2;
tmp = e2->next;
e2->next = e1;
buffer[toIndex]->len++;
prev = e2;
e2 = tmp;
} else {
prev = e1;
e1 = e1->next;
}
}
while (e1 != NULL && e2 != NULL) {
if (CompareElements(e1, e2) >= 0) {
tmp = e2->next;
prev->next = e2;
e2->next = e1;
buffer[toIndex]->len++;
prev = e2;
e2 = tmp;
} else {
prev = e1;
e1 = e1->next;
}
}
while (e2 != NULL) {
tmp = e2->next;
buffer[toIndex]->addToTail(e2);
e2 = tmp;
}
}
static int compareBySizeAsc(const void* a, const void* b)
{
return ((*(LinkedList**)a)->len - (*(LinkedList**)b)->len);
}
void mergeLists(LinkedList** buffer, int &bufferLength)
{
int count = bufferLength * 3 / 4;
qsort(buffer, bufferLength, sizeof(LinkedList*), compareBySizeAsc);
int i, j;
for (i = 1; i <= count; i++) {
performMerge(buffer, 0, i);
}
// i == count + 1
for (j = i; j < bufferLength; j++) {
buffer[j - i + 1] = buffer[j];
}
bufferLength = bufferLength - i + 1;
}
LinkedList* voronkaSort(LinkedList* &list)
{
const int maxBufferSize = 1024;
LinkedList** buffer = new LinkedList*[maxBufferSize];
int bufferLength = 0;
LinkedList* voronka = new LinkedList();
Element* next = NULL;
for (Element* cur = list->head; cur != NULL; cur = next) {
next = cur->next;
if (voronka->len == 0) {
voronka->addToTail(cur);
continue;
} else {
if (CompareElements(cur, voronka->tail) >= 0) {
voronka->addToTail(cur);
continue;
} else if (CompareElements(cur, voronka->head) <= 0) {
voronka->addToHead(cur);
continue;
}
}
if (bufferLength == maxBufferSize) {
mergeLists(buffer, bufferLength);
}
buffer[bufferLength] = voronka;
bufferLength++;
voronka = new LinkedList();
voronka->addToTail(cur);
}
if (bufferLength == maxBufferSize) {
mergeLists(buffer, bufferLength);
}
if (voronka->len > 0) {
buffer[bufferLength] = voronka;
bufferLength++;
}
for (int i = 1; i < bufferLength; i++) {
performMerge(buffer, 0, i);
}
list = buffer[0];
delete []buffer;
}
void quickSort(char** arr, int start, int end)
{
int mid = (start + end) / 2;
char* midValue = arr[mid];
DataWrapper data(midValue, strlen(midValue));
Element midValueElement;
midValueElement.data = &data;
midValueElement.next = NULL;
Element arrElement;
DataWrapper arrData(NULL, 0);
arrElement.data = &arrData;
arrElement.next = NULL;
int i = start, j = end;
int p;
while (i <= j) {
arrData.pRawData = arr[i];
arrData.len = strlen(arr[i]);
while (CompareElements(&arrElement, &midValueElement) < 0) {
i++;
arrData.pRawData = arr[i];
arrData.len = strlen(arr[i]);
}
arrData.pRawData = arr[j];
arrData.len = strlen(arr[j]);
while (CompareElements(&arrElement, &midValueElement) > 0) {
j--;
arrData.pRawData = arr[j];
arrData.len = strlen(arr[j]);
}
if (i <= j) {
char* tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
i++;
j--;
}
}
p = i;
if (start < p - 1) {
quickSort(arr, start, p - 1);
}
if (p < end) {
quickSort(arr, p, end);
}
}
static int compareStrings(const void* a, const void* b)
{
return strcmp(*(const char**)a, *(const char**)b);
}
int getTime()
{
struct timeval tp;
gettimeofday(&tp, NULL);
long int ms = tp.tv_sec * 1000 + tp.tv_usec / 1000;
return ms;
}
int main()
{
const int N = 10000;
char** strings = new char*[N];
const char* symbols = "0123456789abcdefghijklmnopqrstuvwxyz";
srand(time(NULL));
int i, j;
const int maxStringLen = 20;
for (i = 0; i < N; i++) {
int sLen = (rand() % maxStringLen) + 1;
strings[i] = new char[sLen + 1];
strings[i][sLen] = '\0';
for (j = 0; j < sLen; j++) {
strings[i][j] = symbols[rand() % 36];
}
}
char** systemSortedStrings = new char*[N];
for (i = 0; i < N; i++) {
systemSortedStrings[i] = strings[i];
}
qsort(systemSortedStrings, N, sizeof(const char*), compareStrings);
int t1, t2;
// voronkaSort
LinkedList* list = new LinkedList();
for (i = 0; i < N; i++) {
DataWrapper* data = new DataWrapper(strings[i], strlen(strings[i]));
Element* element = new Element();
element->data = data;
list->addToTail(element);
}
COMPARE_ELEMENTS_COUNT = 0;
t1 = getTime();
voronkaSort(list);
t2 = getTime();
char** voronkaSortedStrings = new char*[N];
int n = 0;
for (Element* cur = list->head; cur != NULL; cur = cur->next) {
voronkaSortedStrings[n] = cur->data->pRawData;
n++;
}
printf("voronkaSort\n");
for (i = 0; i < N; i++) {
if (strcmp(voronkaSortedStrings[i], systemSortedStrings[i]) != 0) {
printf("ERROR: incorrect sorting\n");
break;
}
}
if (i == N) {
printf("correct sorting\n");
}
printf("%d ms / %d elements\n", t2 - t1, N);
printf("CompareElements() calls: %d\n", COMPARE_ELEMENTS_COUNT);
// quickSort
char** quickSortSortedStrings = new char*[N];
for (i = 0; i < N; i++) {
quickSortSortedStrings[i] = strings[i];
}
COMPARE_ELEMENTS_COUNT = 0;
t1 = getTime();
quickSort(quickSortSortedStrings, 0, N - 1);
t2 = getTime();
printf("\n");
printf("quickSort\n");
for (i = 0; i < N; i++) {
if (strcmp(quickSortSortedStrings[i], systemSortedStrings[i]) != 0) {
printf("ERROR: incorrect sorting\n");
break;
}
}
if (i == N) {
printf("correct sorting\n");
}
printf("%d ms / %d elements\n", t2 - t1, N);
printf("CompareElements() calls: %d\n", COMPARE_ELEMENTS_COUNT);
return 0;
}