检查数组的排序

时间:2015-07-13 23:41:23

标签: c arrays sorting recursion dynamic

我试图编写一个可以检查动态数组是否已排序的代码,但是我收到错误。代码必须是递归的。

当我输入一个未排序的数组时似乎没有问题,但是当我输入一个已排序的数组时,程序会突然停止:

  

流程返回-1073741571

这是我的代码:

#include <stdio.h>
#include <stdlib.h>
int ordenado(int*);

int main() {
    int i = 0, res = 0;
    int*arr = NULL;
    arr = (int*) malloc(sizeof (int));
    while (arr[i] != 0) {
        i++;
        arr = (int*) realloc(arr, (i + 1) * sizeof (int));
        scanf("%d", &arr[i]);
    }
    res = ordenado(arr);
    printf("\n%d ", res);
    return 0;
}

int ordenado(int* arr) {
    if (arr[0] == 0) {
        return 1;
    }
    if (arr[0] <= arr[1]) {
        return ordenado(arr++);
    }
        else return 0;
    }

3 个答案:

答案 0 :(得分:3)

抱歉,我的第一个回答是不对的。我在下面纠正了。

说明

  1. 我在循环之前添加了scanf("%d", &arr[i]);来填充arr[0]
  2. 我更改了ordenado功能
    1. 点击0然后return 1
    2. 当您点击x但下一个元素是0然后return 1时(注意||是短路。如果您没有点击0然后有一个下一个元素。所以你也可以在这里查看0。)
    3. 只要两个数字不符合return 0(我认为更快)
    4. 否则,下一个元素是not 0并调用ordenado(++arr)(前缀,而不是后缀)
  3. 关于前缀和后缀的注意事项:

    许多编程语言中前缀和后缀之间的区别是执行顺序。在两个语句中执行之前,假设ij0

    i += ++j;
    

    以上代码相当于此

    j = j + 1;
    i = i + j;
    

    以下代码

    i += j++;
    

    等同于此

    i = i + j;
    j = j + 1;
    

    即。在前缀中,增量发生在计算表达式之前,而在后缀中,增量发生在计算表达式之后。这通常适用于数据类型(即包括指针)。

    您的代码行

    return ordenado(arr++);
    

    等同于

    return ordenado(arr);
    a++;
    

    导致无数次的函数调用,如@BLUEPIXY指出的那样。

    更正代码

    #include <stdio.h>
    #include <stdlib.h>
    int ordenado(int*);
    
    int main() {
            int i = 0, res = 0;
            int* arr = NULL;
            arr = (int*) malloc(sizeof (int));
            scanf("%d", &arr[i]);
            while (arr[i] != 0) {
                    i++;
                    arr = (int*) realloc(arr, (i + 1) * sizeof (int));
                    scanf("%d", &arr[i]);
            }
            res = ordenado(arr);
            printf("\n%d ", res);
            return 0;
    }
    
    int ordenado(int* arr) {
            if (arr[0] == 0 || arr[1] == 0)
                    return 1;
            if (arr[0] > arr[1])
                    return 0;
            else
                    return ordenado(++arr);
    }
    

    输入和输出示例:

    Input:  0
    Output: 1
    
    Input:  1 newline 0
    Output: 1
    
    Input:  1 newline 2 newline 3 newline 0
    Output: 1
    
    Input:  2 newline 1 newline 0
    Output: 0
    
    Input:  1 newline 2 newline 3 newline 2 newline 3 newline 0
    Output: 0
    

答案 1 :(得分:2)

在这些方面:

arr = malloc(sizeof (int));
while (arr[i] != 0)

你不能指望具有任何特定价值的malloc内存。它是未初始化

看起来你正在使用输入零作为哨兵。正确的方法是:

int i = 0;
int *arr = malloc(sizeof (int));
do {
    i++;
    arr = realloc (arr, (i + 1) * sizeof (int));
    scanf ("%d", &arr[i-1]);
} while (arr[i-1] != 0);

我还修复了元素零没有分配值。

我怀疑您遇到的错误是由失控的递归引起的。

答案 2 :(得分:1)

您的代码有多个问题:

  • 你在存储它之前读取了数组的第一个元素:它是未初始化的,即使只读它也会调用未定义的行为。
  • 您永远不会将第一个元素存储在数组中(偏移0
  • 如果数组中至少有一个非零元素,当您比较最后两个元素时,由于最后一个元素为0,您将获得潜在的不匹配;
  • 当您递归时,在递增之前传递arr,从而导致无限递归。您收到错误的事实证明编译器不处理尾递归,并且您的代码最终因堆栈溢出而失败。

如果您可以更改ordenado函数的API,则应该传递数组中实际元素的数量。这个函数应该是递归的,如果编译器没有检测到尾递归,选择一个限制递归以避免堆栈溢出的算法。

这是我的建议:

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

int ordenado(int *array, int count);

int main() {
    int i = 0, n, res;
    int *arr = NULL;
    while (scanf("%d", &n) == 1 && n != 0) {
        arr = realloc(arr, (i + 1) * sizeof(int));
        if (!arr) {
            printf("out of memory\n");
            return 1;
        }
        arr[i++] = n;
    }
    res = ordenado(arr, i);
    printf("%d\n", res);
    return 0;
}

int ordenado(int *arr, int n) {
    int m = n >> 1;
    return (m == 0) ||
           (ordenado(arr, m) && arr[m - 1] <= arr[m] && ordenado(arr + m, n - m));
}

注意:一次重新分配一个int数组是非常低效的,但不是讨论的主题。