【问题标题】:Insertion Sort Doing Nothing插入排序什么都不做
【发布时间】:2012-08-14 20:48:14
【问题描述】:

我昨天写了下面的插入排序(我3天前开始学习C)。由于某种原因,排序不会修改数组AT ALL

#include <stdio.h>
int *insert(int arr[], int index, int item);
int *isort(int arr[]);
int main() {
    int a[17] = {1, 2, 9, 5, 3, 2, 1, 6, 5, 9, 0, 1, 3, 4, 2, 3, 4};
    int *b = isort(a);
    for (int i = 0; i < 17; i += 1) {
        printf("%d ", b[i]);
    }
    return 0;
}
int *insert(int arr[], int index, int item) {
    --index;
    while (index >= 0 && item < arr[index]) {
        arr[index + 1] = arr[index];
        --index;
    }
    arr[index + 1] = item;
    return arr;
}
int *isort(int arr[]) {
    for (int i = 1; i < sizeof(arr) - 1; i++) {
        arr = insert(arr, i, arr[i]);
    }
    return arr;
}

我认为它可能是我的编译器,因为我正在运行一个非 unix 机器上的编译器:lcc-win,但我不确定。我在这里缺少一些基本的东西吗?

【问题讨论】:

  • @Blastfurnace 因为在 C 中,没有索引的数组引用指针。
  • @PeterGluck:我知道,对不起,我应该更清楚地说明我的评论是一个链接。这个关于传递数组的问题已经被问过很多次了,所以我找到了一个类似的相关问题和答案。
  • @Blastfurnace 对,抱歉我错过了链接突出显示!

标签: c windows algorithm sorting lcc-win32


【解决方案1】:
int *isort(int arr[]) {
    for (int i = 1; i < sizeof(arr) - 1; i++) {
        arr = insert(arr, i, arr[i]);
    }
    return arr;
}

在这个函数中sizeof(arr)实际上返回的是指针的大小而不是数组的大小。

在 C 中一个特殊的规则是说数组参数实际上被调整为对应指针类型的参数。

即:

int *isort(int arr[]) { /* ... */ }

等价于:

int *isort(int *arr) { /* ... */ }

要解决此问题,请在您的函数中添加一个采用数组大小​​的新参数:

int *isort(int arr[], size_t size) { /* ... */ }

【讨论】:

  • 那我应该放什么来代替sizeof?
  • @BobbyTables,C 中的数组需要一个大小参数。
  • 非常感谢,辛苦了!只是想知道,为什么 size_t 而不是 int 或 long?以前从未见过这种类型
  • @BobbyTables 因为sizeof 产生一个size_t 类型的值,但intlong 在您的程序中也可以。
【解决方案2】:

如前所述,第一个问题是 isort 函数在指针上使用 sizeof 运算符。乍一看,C 处理数组的方式有点奇怪。数组的名称是指向其第一个元素的指针。所以当你像这样调用 isort 时:

int *b = isort(a);

您只是将指向数组的指针压入堆栈。在isort的定义中,

int *isort(int arr[])

声明 arr 是一个指向 int 的指针,就像

int *isort(int *arr)

C 在这方面更加令人困惑:如果你说过:

int *isort(int arr[17])

arr 变量是 still 只是一个指向 int 的指针......这里的“17”被丢弃了!即使使用这种语法,sizeof(arr) 仍然是指向 int 的指针的大小。

在 32 位系统 (ILP32) 上,sizeof(arr) 将始终为 4,无论数组有多大。

因此,需要将数组的大小传递给 isort。一个很好的通用方法是定义这样的宏:

#define NITEMS(arr) (sizeof(arr)/sizeof(arr[0]))

这将计算任意类型数组中元素的数量。

您的下一个问题更多是样式问题,而不是实际错误:

arr = insert(arr, i, arr[i]);

这会通过引用“arr”来调用插入函数。通过该引用修改数组,然后返回指向该数组的指针。它总是和你一开始发送的指针相同,所以这个赋值实际上什么也没做,没有害处。就像我说的,风格问题,而不是代码错误。

最后一个问题是您的 isort 函数会短暂停止(在您纠正 sizeof 问题之后),因为您从 1 变为 sizeof-1。这是一个固定版本:

#include <stdio.h>
#define NITEMS(arr) (sizeof(arr)/sizeof(arr[0]))

int *insert(int arr[], int index, int item);
int *isort(int arr[], size_t nitems);
int main() {
    int a[17] = {1, 2, 9, 5, 3, 2, 1, 6, 5, 9, 0, 1, 3, 4, 2, 3, 4};
    int *b = isort(a, NITEMS(a));
    for (int i = 0; i < NITEMS(a); i += 1) {
        printf("%d ", b[i]);
    }
    printf("\n");
    return 0;
}

int *insert(int arr[], int index, int item) {
    --index;
    while (index >= 0 && item < arr[index]) {
        arr[index + 1] = arr[index];
        --index;
    }
    arr[index + 1] = item;
    return arr;
}

int *isort(int arr[], size_t nitems) {
    for (int i = 1; i < nitems; i++) {
        insert(arr, i, arr[i]);
    }
    return arr;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-30
    • 1970-01-01
    • 2019-03-08
    相关资源
    最近更新 更多