gpt4 book ai didi

c - 为什么这种优化会导致我的合并排序失败?

转载 作者:行者123 更新时间:2023-12-04 10:51:00 27 4
gpt4 key购买 nike

我正在研究非递归归并排序,我想出了一个优化方法可以稍微加快它的速度。要点是,我不是合并到一个临时缓冲区然后每次都将其复制回数据位置,而是先在一个方向合并,然后在另一个方向合并。这应该可以完美地工作,因为缓冲区大小相同且数据相同。

但是,当我尝试这样做时,我的数组并没有完全排序。有一些项目,有时在最后,有时在中间,是不合适的。我在下面的示例中包含了我用来测试我的代码的函数。

我尽我所能制作 MWE,但测试需要几个辅助函数。

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>

#define MIN(x, y) ((x) > (y) ? (y) : (x))
#define OPTIMIZE true // if true, then merge in alternating directions

void merge(int* src, int* dest, size_t start, size_t mid, size_t end);
void merge_sort(int* data, size_t length);

/* MERGESORT IMPLEMENTATION {{{1 */

void merge(int* src, int* dest, size_t start, size_t mid, size_t end) {
int i, j, k;
for (i = start, j = mid, k = start; i < mid && j < end; k++) {
if (src[i] > src[j]) {
dest[k] = src[j];
j++;
} else {
dest[k] = src[i];
i++;
}
}
for (; i < mid; i++, k++) {
dest[k] = src[i];
}
for (; j < end; j++, k++) {
dest[k] = src[j];
}
}

void merge_sort(int* data, size_t length) {
int* buffer = malloc(length * sizeof(int));
int swap = false;
for (size_t i = 0; i < length; i++) {
buffer[i] = data[i];
}

#if OPTIMIZE
for (size_t step = 1; step < length; step *= 2, swap = !swap) {
int* src = swap ? buffer : data;
int* dest = swap ? data : buffer;
for (size_t i = 0; i < length - step; i += (step * 2)) {
merge(src, dest, i, i + step, MIN(length, i + (step * 2)));
}
}
if (swap) {
for (size_t i = 0; i < length; i++) {
data[i] = buffer[i];
}
}
#else
for (size_t step = 1; step < length; step *= 2, swap = !swap) {
int* src = data;
int* dest = buffer;
for (size_t i = 0; i < length - step; i += (step * 2)) {
merge(src, dest, i, i + step, MIN(length, i + (step * 2)));
}
for (size_t i = 0; i < length; i++) {
data[i] = buffer[i];
}
}
#endif

free(buffer);
}

/* UTILITY FUNCTIONS {{{1 */

void check_sorted(int* data, size_t length) {
for (size_t i = 0; i < length - 1; i++) {
if (data[i] != i) {
printf("%ld: %d\n", i, data[i]);
}
}
}

void shuffle(int* data, size_t length) {
for (size_t i = 1; i < length; i++) {
size_t index = rand() % (i + 1);
int temp = data[index];
data[index] = data[i];
data[i] = temp;
}
}

/* MAIN {{{1 */

int main() {
size_t length = 200;
int* data = malloc(length * sizeof(int));

for (size_t i = 0; i < length; i++) {
data[i] = (int)i;
}
shuffle(data, length);

merge_sort(data, length);
check_sorted(data, length);

free(data);
return 0;
}

最佳答案

这似乎有效。评论中指出的修复:

void merge_sort(int* data, size_t length) {
int* buffer = malloc(length * sizeof(int));
int swap = false;
/* ** removed the initial copy */

#if OPTIMIZE
for (size_t step = 1; step < length; step *= 2, swap = !swap) {
int* src = swap ? buffer : data;
int* dest = swap ? data : buffer;
size_t i; /* fix, using i in 2nd loop */
for (i = 0; i < length - step; i += (step * 2)) { /* fix (removed size_t) */
merge(src, dest, i, i + step, MIN(length, i + (step * 2)));
}
for( ; i < length; i++) /* fix, copy single run if present */
dest[i] = src[i]; /* fix, copy single run if present */
}
if (swap) {
for (size_t i = 0; i < length; i++) {
data[i] = buffer[i];
}
}
#else

替代修复:

    for (size_t step = 1; step < length; step *= 2, swap = !swap) {
int* src = swap ? buffer : data;
int* dest = swap ? data : buffer;
for (size_t i = 0; i < length; i += (step * 2)) { /* fix */
merge(src, dest, i, MIN(length, i+step), MIN(length, i+(step * 2))); /* fix */
}

关于c - 为什么这种优化会导致我的合并排序失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59515306/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com