在C中排序子阵列而不是整个数组?

问题描述 投票:-1回答:1

因此,在我写的这个小游戏中,我有一副n_C卡片,每张卡片都有一个唯一的整数值。有n_P球员各自手持n_H卡。

甲板和手共用一个阵列,如下所示:玩家i_P的手牌包含从deck[i_P * n_Hdeck[i_P * (n_H + 1) - 1]的所有牌。所有球员组合总是比n_C卡少。

现在我想对每个玩家的牌进行排序,但不是整个牌组(显然,因为这会在牌手之间移动一些牌)。我这样做是这样的:

void sort_hands(char * deck, size_t n_P) {
    for (size_t i_P = 0; i_P < n_P; i_P++)
        sort_cards(deck + i_P * n_H, n_H);
}

然后,使用插入排序(此函数将对整个数组进行排序):

void sort_cards(char * cards, size_t n) {
    for (size_t i = 0; i < n; i++) {
        for (size_t j = i - 1; j >= 0; j--) {
            if (cards[j] > cards[j + 1])
                card_swap(cards, j, j + 1);
            else
                break;
    }
}

*注意:card_swapdoes正是你所期望的,它只有3个陈述。

n_Cand和n_H都是#define'd常数,n_P是局部变量。当我用一个洗牌的甲板和params n_C = 104, n_H = 10, n_P = 3运行上面的代码时,我得到:

0:74 31 53 46 42 75 72 77 70 49

1:76 86 99 78 11 94 61 14 41 87

2:40 26 92 5 9 3 66 63 101 98

在子阵列排序之前,例如:

0:3 5 9 11 31 42 46 49 53 74

1:61 70 75 72 76 77 78 86 94 99

2:14 26 40 41 63 66 87 92 98 101

然后。正如我们所看到的,有些牌在他们不应该的时候已经移动了。但是牌组并没有按照所有牌的方式进行分类(例如参见玩家2手中的14。这怎么可能?我看到它的方式,我的编码技巧没有错,但编译器似乎在弄乱我。

我用VS15 C ++编译器和GCC都观察到了这种行为。

c++ c arrays sorting
1个回答
2
投票

我编译了你的sort_cards()函数(在提供缺少的}之后),在Mac上使用GCC 7.2.0和命令行:

gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes \
    -Wstrict-prototypes -c cards53.c

有了这些选项(关键的一个是-Wextra),它会立即发出警告:

cards53.c:31:34: error: comparison of unsigned expression >= 0 is always true [-Werror=type-limits]
         for (size_t j = i - 1; j >= 0; j--)

这表明存在严重问题。特别是在外环的第一次迭代中,i0,所以i - 1是一个非常大的数字。坦率地说,你声称该函数将成功排序整个数组是虚假的。它不会。并且我不会运行无法使用显示的命令行编译的代码。

如果您修复了该功能,那么您的代码就可以了。我用了:

#include <stdio.h>

#define n_H 10
#define n_C 104

static inline void card_swap(char *deck, int i1, int i2)
{
    char t = deck[i1];
    deck[i1] = deck[i2];
    deck[i2] = t;
}

static void sort_cards(char *cards, size_t n)
{
    for (size_t i = 1; i < n; i++)
    {
        for (size_t j = i; j-- > 0; )
        {
            if (cards[j] > cards[j + 1])
                card_swap(cards, j, j + 1);
            else
                break;
        }
    }
}

static void sort_hands(char *deck, size_t n_P)
{
    for (size_t i_P = 0; i_P < n_P; i_P++)
        sort_cards(deck + i_P * n_H, n_H);
}

static void dump_hands(const char *tag, const char *deck, size_t n_P)
{
    printf("%s:\n", tag);
    for (size_t p = 0; p < n_P; p++)
    {
        printf("Player %zu:", p + 1);
        const char *hand = deck + p * n_H;
        for (int i = 0; i < n_H; i++)
            printf(" %3d", hand[i]);
        putchar('\n');
    }
}

int main(void)
{
    char deck[n_C] =
    {
        74,  31,  53,  46,  42,  75,  72,  77,  70,  49,
        76,  86,  99,  78,  11,  94,  61,  14,  41,  87,
        40,  26,  92,   5,   9,   3,  66,  63, 101,  98,
    };
    int n_P = 3;
    dump_hands("Before", deck, n_P);
    sort_hands(deck, n_P);
    dump_hands("After", deck, n_P);
    return 0;
}

使用您提供的样本数据初始化数组;残留物全部为零,但这对于此练习无关紧要。

样本输出:

Before:
Player 1:  74  31  53  46  42  75  72  77  70  49
Player 2:  76  86  99  78  11  94  61  14  41  87
Player 3:  40  26  92   5   9   3  66  63 101  98
After:
Player 1:  31  42  46  49  53  70  72  74  75  77
Player 2:  11  14  41  61  76  78  86  87  94  99
Player 3:   3   5   9  26  40  63  66  92  98 101

检查显示每个子数组已正确排序。

© www.soinside.com 2019 - 2024. All rights reserved.