Search code examples
c++arraysfunctionsortingstructure

C++ New Order for Structure Array


I have a structure array, where each structure has an id (int) and an value called aktiv (boolean). I want to pass the structure array to a function which sorts the structure. The structures in the array with an aktiv value of 0 (false) should be at the end of my array.

I thought i create an second array where i save my values temporarly and then put everything from the second array again in the first, but it work. What am i doing wrong or what should i change. Thanks in advance. My code:

void naende(Item itf[], int dim) { 
Item* temp_arr = new Item[dim]{};
int temp = 0;
for (int i = 0; i < dim; i++) {
    if (itf[i].aktiv == 0) {
        temp_arr[dim - i].id = itf[i].id;
        temp_arr[dim - i].aktiv = itf[i].aktiv;
        //cout << temp_arr[i].id << endl;
    }
    else if (itf[i].aktiv == 1) {
        temp_arr[temp].id = itf[i].id;
        temp_arr[temp].aktiv = itf[i].aktiv;
        temp++;
    }
}

for (int j = 0; j < dim; j++) {
    itf[j] = temp_arr[j];
}
}

Solution

  • Given what you've posted, if the goal is to move all aktiv items that are 0 to the back of the array, then std::partition can be used.

    #include <algorithm>
    
    void naende(Item itf[], int dim) 
    { 
       std::partition(itf, itf + dim, [&](const Item& it) { return it.aktiv == 1; });
    }
    

    The code above places all aktiv entries equal to 1 to the left of the array, and all aktiv entries equal to 0 to the right of the array.

    If the relative order needs to be maintained, then std::stable_partition can be used:

    #include <algorithm>
    
    void naende(Item itf[], int dim) 
    { 
       std::stable_partition(itf, itf + dim, [&](const Item& it) { return it.aktiv == 1; });
    }
    

    The point of the above code is to emphasize that there are STL algorithm or a set of STL algorithm functions that can be used to do a lot of work that would usually require a hand-coded solution (which would have to be debugged if there are errors). Using the functions above, the STL algorithm functions do not fail if given valid parameters.


    Now let's say you can't use std::partition, and order need not be preserved. If this is the case, then the way this is accomplished can be to simply have two pointers, and call std::swap in a loop at strategic times.

    The way it works is that you would have an index that goes forward in the array, and another index that starts at the end of the array and goes backwards. The incrementing of the first index, the decrementing of the end index, and the calls to std::swap would be done this way:

    #include <algorithm>
    #include <iostream>
    
    struct Item
    {
        int id;
        int aktiv;
    };
    
    void naende(Item itf[], int dim)
    {
        int leftpos = 0;
        int rightpos = dim - 1;
        while (leftpos < rightpos)
        {
            if (itf[leftpos].aktiv == 0)
            {
                std::swap(itf[leftpos], itf[rightpos]);
                --rightpos;
            }
            else
                ++leftpos;
        }
    }
    
    int main()
    {
        Item item[] = { {1,1},{2,0},{34,0},{32,1},{12,0},{12,1},{21,1} };
        naende(item, 7);
        for (int i = 0; i < 7; ++i)
            std::cout << item[i].id << " " << item[i].aktiv << "\n";
    }
    

    Output:

    1 1
    21 1
    12 1
    32 1
    12 0
    34 0
    2 0
    

    We basically only go forward with the left index if we detect that the aktiv value is 1. If it isn't 1, then we put that item in the back by swapping with the back item, then we decrement the back item index.

    For stable items, I will leave that as an exercise.