【问题标题】:Segregating an array for even and odd numbers将数组分离为偶数和奇数
【发布时间】:2012-01-20 20:15:20
【问题描述】:

我已经实现了一种算法来更改数组,以便将所有偶数移到数组的开头,将旧数字移到数组的末尾。这是我的程序:-

#include <iostream>
using namespace std;

void print(int arr[], int size) {
    for(int i=0;i<size;i++) {
        cout<<arr[i]<<" ";
    }
    cout<<endl;
}

void segregate(int arr[], int size) {
    int l=0, h=size-1;

    while(l<h) {

        while(!(arr[l]%2) && l<size) {
            l++;
        }
        while((arr[h]%2) && h >=0) {
            h--;
        }
        swap(arr[l], arr[h]);
    }
}

int main() {

    int arr[] = {1,2,3,4,5,6,7,8,9};
    int size = 9;

    print(arr,size);

    segregate(arr,size);

    print(arr,size);

    return 0;
}

我没有得到预期的结果

1 2 3 4 5 6 7 8 9 
8 2 6 5 4 3 7 1 9 

我错过了什么?

【问题讨论】:

  • 建议:使用sizeof(arr) 查找数组的size
  • 请注意,sizeof(arr)bytes 为单位返回数组的大小,而不是以元素为单位。使用sizeof(arr) / sizeof(*arr)获取元素个数。

标签: c++ arrays algorithm


【解决方案1】:

您尝试执行的操作也称为分区。标准库提供了两种算法来做到这一点:std::partitionstd::stable_partition

int main()
{
   int arr[] = {1,2,3,4,5,6,7,8,9};

   auto split = std::partition( std::begin(arr), std::end( arr ),
         []( int a ) { return ! a%2; } );

   // [ begin, split ) are all even
   // [ split, end ) are all odd
}

http://ideone.com/kZI5Zh

如果您仍然对writing your own 感兴趣,cppreferencestd::partition 的描述包含等效代码。
您的版本在交换之前缺少 if 语句。只有在左边有奇数时才应交换。

【讨论】:

    【解决方案2】:

    问题一:

    只有当l 没有越过h 时,你才需要调用swap,你一直在调用它。

    考虑数组{2,1},它已经被分割了。
    现在在两个内部while循环之后l将是1h将是0。在您的情况下,您将继续进行交换,但实际上并不需要交换,因为l 已经越过h。 当这种情况发生时,数组已经被隔离了。

    所以改变

    swap(arr[l], arr[h]);
    

    if(l<h) {
        swap(arr[l], arr[h]);
    }
    

    问题 2:

    您的内部 while 循环中的条件顺序也必须颠倒。你正在检查

    while(number at index l is even AND l is a valid index) {
        l++;
    }
    

    这是不正确的。考虑一个数组{2,4},现在在上述while循环中的某个点l将是2,然后你继续访问arr[2],它不存在。

    你需要的是:

    while(l is a valid index AND number at index l is even) {
        l++;
    }
    

    【讨论】:

      【解决方案3】:

      就这么简单:

      void partitionEvenOdd(int array[], int arrayLength, int &firstOdd)
      {
          firstOdd = 0;
          for (int i = 0; i < arrayLength; i++) {
              if (array[i]%2 == 0) {
                  swap(array[firstOdd], array[i]);
                  firstOdd++;
              }
          }
      }
      

      【讨论】:

        【解决方案4】:

        你不能只使用标准排序吗?

        类似:

        #include <stdio.h>
        #include <stdlib.h>
        
        int values[] = { 40, 10, 100, 90, 20, 25 };
        
        int compare (const void * a, const void * b)
        {
          // return -1 a-even and b-odd
          //        0  both even or both odd 
          //        1  b-even and a-odd
        }
        
        qsort (values, 6, sizeof(int), compare);
        

        【讨论】:

        • 除非qsort() 进行三向分区,否则您将浪费一个日志因子。
        • 但它易于理解且易于维护。并且根据数组的大小,实际上可能并不重要。
        • 是的,“可维护性”和易于使用是我的第一个目标。在性能方面——对于小数组来说应该差不多,作者没有提到大小。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-08-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-08
        相关资源
        最近更新 更多