作为练习,我try 实现合并排序算法.这是我的代码:

#include <stdio.h>

void printArray(int *array) {
    int i;
    for (i=0; i<20; i++) {
        printf("%d ", array[i]);
    }
    printf("\n");
}

void merge(int *array, int *temp, int left, int mid, int right) {
  int i=left, j=mid, k=left;
  while (i<mid && j<right) {
    if (array[i] > array[j]) {
      temp[k++]=array[j++];
    } else {
      temp[k++]=array[i++];
    }
  }
  while (i<mid) {
    temp[k++]=array[i++];
  }
  while (j<right) {
    temp[k++]=array[j++];
  }
  for (i=left; i<right; i++) {
    array[i]=temp[i];
  }
}

void mergeSort(int *array, int size) {
  int temp[size];
  int i,j;
  for (j=1; j<=size; j*=2) {
    printf("\n%d\n",j);
    for (i=0; i<size; i+=2*j) {
      if (i+2*j<size) {
        merge(array,temp, i, i+j, i+2*j);
      } else {
        merge(array,temp, i, i+j, size);
      }
    }
  }
}

int main() {
    int array[] = {83,86,77,15,93,35,86,92,49,21,62,27,90,59,63,26,40,26,72,36};
    printArray(array);
    mergeSort(array, 20);
    printArray(array);
}

mergeSort内,我预计f的迭代会在f等于16时停止,因为size等于20,但实际上它上升到8;事实上,列表并不是完全有序的.以下是输出:

83 86 77 15 93 35 86 92 49 21 62 27 90 59 63 26 40 26 72 36 

1

2

4

8
15 21 26 27 35 49 59 62 63 77 83 86 86 90 92 93 26 36 40 72

然后,我try 编译相同的代码,将GCC的优化选项设置为O1、O2或O3,得到了我预期的结果:

83 86 77 15 93 35 86 92 49 21 62 27 90 59 63 26 40 26 72 36 

1

2

4

8

16
15 21 26 26 27 35 36 40 49 59 62 63 72 77 83 86 86 90 92 93

怎么一回事?

推荐答案

mergeSort()中的问题是,i+j可能大于size,导致merge()被调用,而mid的值超出范围.例如,当size是20,j是8,i是16时,mid的值i+j将是24,大于size.在merge()中,循环while (i < mid) {temp[k++] = array[i]++;}将复制索引为16到23(包括16和23)的元素,但索引为20到23(包括20和23)的元素在数组的边界之外,导致undefined behavior.

要纠正该问题,请注意,只有当剩余的未合并部分长于当前块大小j(否则,剩余的未合并部分已经完全排序)时,才需要调用merge().i+j<size的时候就是这样,只有j<size的时候才能这样.因此,将for (j=1; j<=size; j*=2)更改为for (j=1; j<size; j*=2),并将for (i=0; i<size; i+=2*j)更改为for (i=0; i+j<size; i+=2*j).

C++相关问答推荐

修改pGM使用指针填充2-D数组但不起作用

错误:在.h程序中重新定义 struct

如何将已分配的数组(运行时已知的大小)放入 struct 中?

ATmega328P EEPROM未写入

错误Cygwin_Except::Open_stackdupfile:正在转储堆栈跟踪是什么?

为什么此共享库没有预期的依赖项?

CGO:如何防止在使用CGO在包中包含C头文件时出现多个定义...&q;错误?

如何在C中只对字符串(包含数字、单词等)中的数字进行重复操作?

如何在VSCode中创建和使用我自己的C库?

Fprintf正在写入多个 struct 成员,并且数据过剩

C";中的ANN运行时判断失败#2-变量outputLayer;周围的堆栈已损坏.运行后出错

为什么我在C代码中得到一个不完整的类型?

在C程序中使用Beaglebone Black UART的问题

无法识别C编程语言的语法,如书中所示

生产者消费者计数器意外输出的C代码

我正在使用c学习数据 struct ,在学习堆栈时,我试图将中缀转换为后缀,并编写了这段代码.代码未给出输出

为什么<到达*时不会转换为>?

C23 中是否有 __attribute__((nonnull)) 的等效项?

C99 的 %zu 格式说明符不起作用

用于内存布局的size命令(文本、数据、bss)