【问题标题】:To sort an array in required manner以所需的方式对数组进行排序
【发布时间】:2017-06-27 15:22:29
【问题描述】:

我需要将奇数位置的元素降序排序,偶数位置的元素升序排序。这是我的代码,我无法打破第一个循环。

#include<stdio.h>

int main()
{
    int n, t;

    printf("Enter the size of the array\n");
    scanf("%d", &n);
    int i, a[n];

    if ((n > 20) || (n <= 0))
        printf("Invalid Size");
    else
    {
        printf("Enter the values\n");
        for (i = 0; i < n; i++)
        {
            scanf("%d", &a[i]);
        }

        for (i = 0; i < n; i + 2)
        {
            if (a[i] > a[i + 2])
            {
                t = a[i];
                a[i] = a[i + 2];
                a[i + 2] = t;
            }
        }
        for (i = 1; i < n; i + 2)
        {
            if (a[i] < a[i + 2])
            {
                t = a[i];
                a[i] = a[i + 2];
                a[i + 2] = t;
            }
        }
        for (i = 0; i < n; i++)
        {
            printf("%d\n", a[i]);
        }
    }
}

【问题讨论】:

  • ;i+2 --> ;i += 2 ?并注意越界错误。
  • @JustinJ.:VLA 是标准的。这是 C,不是 C++。
  • for (i = 0; i &lt; n; i + 2) -> for (i = 0; i &lt; n-2; i += 2) 避免访问数组外,即使用i &lt; n-2;
  • 您并没有真正进行排序。您的代码当时只是交换了两个元素。要对数组进行排序,您需要与所有其他元素进行比较。无论如何,试试这个 - 1)将数组分成两个数组,2)在每个数组上使用 qsort,3)重建整个数组。这样就不用自己写排序代码了
  • @JustinJ.:好吧,如果您将使用仅适用于 C90 的古老编译器,那么仅使用古老的功能就会遇到问题。自上个千年(C99)结束以来,VLA 一直是标准 C 的一部分。微软还没有意识到新千年的事实是一个单独的问题。

标签: c arrays sorting bubble-sort


【解决方案1】:

对于根据 C 标准的初学者,不带参数的函数 main 应声明为

int main( void )

将变量n 声明为具有int 类型没有太大意义,然后检查其值是否小于零。最好将其声明为 size_t 类型。

并且数组要在校验后声明

if ((n > 20) || (n <= 0))
    printf("Invalid Size");
else
{
    int a[n];
    //...

在这样的循环中

for (i = 0; i < n; i + 2)

变量i 没有增加。很明显你的意思是i += 2

并且循环仅将第一个最小偶数元素和第一个最大奇数元素移动到数组的末尾。您需要额外的循环来对数组的其他元素执行相同的操作。那就是冒泡排序算法的实现是不正确的。

这是一个演示程序,展示了如何根据数组的偶数和奇数元素的要求对数组进行排序。

#include <stdio.h>

#define N   20

int main(void) 
{
    int a[N] = { 18, 1, 16, 3, 14, 5, 12, 7, 10, 9, 8, 11, 6, 13, 4, 15, 2, 17, 0, 19 };

    for ( size_t i = 0; i < N; i++ )
    {
        printf( "%d ", a[i] );
    }
    putchar( '\n' );

    for ( size_t n = N, last; !( n < 3 ); n = last )
    {
        for ( size_t i = last = 2; i < n; i++ )
        {
            if ( ( i % 2 == 0 && a[i] < a[i - 2] ) ||
                 ( i % 2 == 1 && a[i - 2] < a[i] ) )
            {
                int tmp = a[i];
                a[i] = a[i - 2];
                a[i - 2] = tmp;
                last = i;
            }
        }
    }

    for ( size_t i = 0; i < N; i++ )
    {
        printf( "%d ", a[i] );
    }
    putchar( '\n' );

    return 0;
}

程序输出是

18 1 16 3 14 5 12 7 10 9 8 11 6 13 4 15 2 17 0 19 
0 19 2 17 4 15 6 13 8 11 10 9 12 7 14 5 16 3 18 1 

【讨论】:

    【解决方案2】:
    • 最明显的问题是您的for 永远不会结束,因为i 从未真正更新过。 for (i = 0; i &lt; n; i + 2) 中的 i+2 不会更新 i,它会永远保持其初始值。 改用for (i = 0; i &lt; n; i=i+2) 之类的东西。
    • 第二个问题是您并没有真正执行排序。 我猜你正在尝试实现某种bubble sort。 它使用比较进行排序。使用小于n logn 操作对数组进行排序是不可能的(使用比较排序时)。您正在以线性时间对数组进行排序,这对您来说应该是一个危险信号。

    尝试添加另一个for,如下所示:

    for (i = 0; i < n; i+= 2)
        for (j = i+2; j < n; j+= 2)
            if (a[i] > a[j])
            {
                t = a[i];
                a[i] = a[j];
                a[j] = t;
            }
    

    然后最重要的是阅读您为什么需要它。

    如果您觉得勇敢,您可以在不使用中间变量 t 的情况下交换整数,如下所示(在此处阅读有关该主题的更多信息:XOR swap):

    if (a[i] > a[j])
    {
        a[i] = a[i]^a[j];
        a[j] = a[j]^a[i];
        a[i] = a[i]^a[j];
    }
    

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-24
      • 2019-08-31
      • 1970-01-01
      • 1970-01-01
      • 2016-07-12
      • 2012-04-12
      相关资源
      最近更新 更多