简体   繁体   中英

Segregating an array for even and odd numbers

I have implemented an algorithm to change an array so that all the even numbers are moved to the beginning of the array and the old numbers to the end of the array. Here is my program :-

#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;
}

I don't get the expected result

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

What am I missing?

What you're trying to do is also called partitioning. The standard library provides two algorithms to do just that: std::partition and std::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

If you're still interesting in writing your own , cppreference 's description of std::partition includes the equivalent code.
Your version is missing an if statement right before the swap. You should only swap when there is an odd on the left.

Problem 1:

You need to call the swap only if l has not crossed h , you are calling it always.

Consider the array {2,1} , which is already sgeregated.
Now after the two inner while loops l will be 1 and h will be 0 . In your case you'll go ahead and swap, but a swap is not really needed since l has crossed h . And when that happens the array is already segregated.

So change

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

to

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

Problem 2:

Also the order of conditions in your inner while loops must be reversed. You are checking

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

which is incorrect. Consider an array {2,4} , now at some point in the above while loop l will be 2 and you go ahead and access arr[2] , which does not exist.

What you need is:

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

As simple as it gets:

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++;
        }
    }
}

Can't you just use standard sort?

Something like:

#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);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM