147 lines
3.3 KiB
C
147 lines
3.3 KiB
C
#include "ms.h"
|
|
|
|
void mymerge(int left[], size_t leftlen, int right[], size_t rightlen, int res[])
|
|
{
|
|
size_t i;
|
|
size_t j;
|
|
size_t k;
|
|
|
|
for (i = 0, j = 0, k = 0; i < leftlen && j < rightlen;) {
|
|
if (left[i] <= right[j]) {
|
|
res[k++] = left[i++];
|
|
} else {
|
|
res[k++] = right[j++];
|
|
}
|
|
}
|
|
for (; i < leftlen; ++i) {
|
|
res[k++] = left[i];
|
|
}
|
|
for (; j < rightlen; ++j) {
|
|
res[k++] = right[j];
|
|
}
|
|
}
|
|
|
|
void _mergesort(int arr[], size_t len, int res[])
|
|
{
|
|
size_t mid;
|
|
size_t leftlen;
|
|
size_t rightlen;
|
|
int foo;
|
|
|
|
if (len == 2) {
|
|
if (arr[1] < arr[0]) {
|
|
foo = arr[1];
|
|
arr[1] = arr[0];
|
|
arr[0] = foo;
|
|
}
|
|
return;
|
|
} else if (len < 2) {
|
|
return;
|
|
}
|
|
|
|
mid = (len - 1) / 2;
|
|
leftlen = mid + 1;
|
|
rightlen = len - mid - 1;
|
|
_mergesort(arr, leftlen, res);
|
|
_mergesort(&arr[mid + 1], rightlen, &res[mid + 1]);
|
|
mymerge(arr, leftlen, &arr[mid + 1], rightlen, res);
|
|
memcpy(arr, res, len * sizeof(int));
|
|
}
|
|
|
|
int mymergesort(int arr[], size_t len)
|
|
{
|
|
int *res = (int *)malloc(sizeof(int *) * len);
|
|
if (res == NULL) {
|
|
return -1;
|
|
}
|
|
_mergesort(arr, len, res);
|
|
free(res);
|
|
return 0;
|
|
}
|
|
|
|
int _mergesortp(int arr[], size_t len, int res[], int forklimitsz)
|
|
{
|
|
size_t mid;
|
|
size_t leftlen;
|
|
size_t rightlen;
|
|
int foo;
|
|
pid_t pid, wpid;
|
|
int status;
|
|
|
|
if (len == 2) {
|
|
if (arr[1] < arr[0]) {
|
|
foo = arr[1];
|
|
arr[1] = arr[0];
|
|
arr[0] = foo;
|
|
}
|
|
return 0;
|
|
} else if (len < 2) {
|
|
return 0;
|
|
}
|
|
|
|
mid = (len - 1) / 2;
|
|
leftlen = mid + 1;
|
|
rightlen = len - mid - 1;
|
|
|
|
if (len <= forklimitsz) {
|
|
_mergesort(arr, leftlen, res);
|
|
_mergesort(&arr[mid + 1], rightlen, &res[mid + 1]);
|
|
mymerge(arr, leftlen, &arr[mid + 1], rightlen, res);
|
|
memcpy(arr, res, len * sizeof(int));
|
|
|
|
return 0;
|
|
}
|
|
|
|
pid = fork();
|
|
if (pid < 0) {
|
|
return -1;
|
|
}
|
|
if (pid == 0) { /* child */
|
|
foo = _mergesortp(&arr[mid + 1], rightlen, &res[mid + 1], forklimitsz);
|
|
if (foo < 0) {
|
|
exit(1);
|
|
}
|
|
exit(0);
|
|
} else { /* parent */
|
|
foo = _mergesortp(arr, leftlen, res, forklimitsz);
|
|
if (foo < 0) {
|
|
return foo;
|
|
}
|
|
/* wait child and then merge */
|
|
if ((wpid = waitpid(pid, &status, 0)) != pid) {
|
|
return -1;
|
|
}
|
|
if (status != 0) {
|
|
return status;
|
|
}
|
|
mymerge(arr, leftlen, &arr[mid + 1], rightlen, res);
|
|
memcpy(arr, res, len * sizeof(int));
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int mymergesortp(int arr[], size_t len, int cnt)
|
|
{
|
|
int foo;
|
|
int forklimitsz;
|
|
size_t size = sizeof(int) * len;
|
|
int *arrp = mmap(0, size, PROT_READ | PROT_WRITE,
|
|
MAP_SHARED | MAP_ANON, -1, 0);
|
|
if (arrp == MAP_FAILED) {
|
|
return -1;
|
|
}
|
|
int *resp = mmap(0, size, PROT_READ | PROT_WRITE,
|
|
MAP_SHARED | MAP_ANON, -1, 0);
|
|
if (resp == MAP_FAILED) {
|
|
munmap(arrp, size);
|
|
return -1;
|
|
}
|
|
memcpy(arrp, arr, size);
|
|
forklimitsz = len / cnt;
|
|
foo = _mergesortp(arrp, len, resp, forklimitsz);
|
|
memcpy(arr, arrp, size);
|
|
munmap(arrp, size);
|
|
munmap(resp, size);
|
|
return foo;
|
|
}
|
|
|