结构数组的 C++ 新顺序

C++ New Order for Structure Array

我有一个结构数组,其中每个结构都有一个 id (int) 和一个名为 aktiv (boolean) 的值。 我想将结构数组传递给对结构进行排序的函数。 数组中 aktiv 值为 0(假)的结构应该在我的数组末尾。

我以为我创建了第二个数组,在其中临时保存我的值,然后将第二个数组中的所有内容再次放入第一个数组中,但它起作用了。我做错了什么或者我应该改变什么。提前致谢。我的代码:

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

根据您发布的内容,如果目标是将所有 aktiv 为 0 的项目移动到数组的后面,则可以使用 std::partition

#include <algorithm>

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

上面的代码将所有等于 1 的 aktiv 条目放在数组的左侧,所有 aktiv 等于 0 的条目放在数组的右侧。

如果需要保持相对顺序,那么可以使用std::stable_partition

#include <algorithm>

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

上面代码的重点是强调有STL算法或一组STL算法函数可以用来做很多通常需要手动编码解决方案的工作(这将不得不如有错误进行调试)。使用上述函数,如果给定有效参数,STL 算法函数不会失败。


现在假设您不能使用 std::partition,并且不需要保留顺序。如果是这种情况,那么实现这一点的方法可以是简单地拥有两个指针,并在关键时刻循环调用 std::swap

它的工作方式是您将有一个在数组中向前的索引,以及另一个从数组末尾开始并向后移动的索引。第一个索引的递增,结束索引的递减,以及对 std::swap 的调用将以这种方式完成:

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

输出:

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

如果我们检测到 aktiv 值为 1,我们基本上只用左边的索引前进。如果它不是 1,那么我们通过交换将那个项目放在后面后面的项目,然后我们减少后面的项目索引。

对于稳定的物品,我会把它留作练习。

这是我没有 std::partition 的实现。

#include <iostream>

struct Item {
    int id;
    bool aktiv;
};

//in-place swap
void swap(Item& left, Item& right) {
    left.aktiv ^= right.aktiv;
    right.aktiv ^= left.aktiv;
    left.aktiv ^= right.aktiv;
    left.id ^= right.id;
    right.id ^= left.id;
    left.id ^= right.id;
}

void naende(Item itf[], const size_t dim) {
    if (dim < 2) return;    //array is empty or has one single item, so do nothing
    Item temp = itf[0];     //init the temp to take the first item (adds only 1 more item in memory space)
    size_t rightSwapIndex = dim-1;  //index to put the checked item at the rightmost position
    size_t leftSwapIndex = 0;       //index to put the checked item at the leftmost position
    for (size_t i = 0; i < dim; ++i) {  //consider exactly 'dim' cases (guarantees algorithm to be O(n) time)
        if (!temp.aktiv) {  //needs to moved to the rightmost position
            swap(temp, itf[rightSwapIndex--]);  //swap the temp with the last item; and move the rightSwapIndex to left by one
        } else {
            itf[leftSwapIndex] = temp;      //put the temp at the rightmost index (may have no effect but important!)
            temp = itf[++leftSwapIndex];    //take the next item to consider; and move the leftSwapIndex to right
        }
    }
}

void printDebug(Item array[], const size_t dim) {
    for (size_t i = 0; i < dim; ++i) {
        std::cout<<array[i].id<<"/"<<array[i].aktiv<<" ";
    }
    std::cout<<std::endl;
}

int main() {
    //build some test array with a sample data
    size_t size = 10;
    Item array[size];
    for (size_t i = 0; i < size; ++i) {
        array[i].id = i;
        array[i].aktiv = i%2;   //TODO: test with some other inits as well, like for ex. this one: array[i].aktiv = (i%3)%2;
    }

    //test the function naende()
    printDebug(array, size);    //print out the array before the call
    naende(array, size);        //call our cute function
    printDebug(array, size);    //print out the array after the call
}

输出:

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

具有不同数组初始化的另一个输出(请参阅我上面带有 TODO 的评论行:)

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

你的post不清楚,不过你可以试试这个:

#include <bits/stdc++.h>
using namespace std;

struct Item
{
    int active;
    int id;
};

void SortByStat(Item itf[], int dim)
{
    std::stable_partition(itf,itf + dim ,[](const Item &a){return a.active == 1;});

    //std::sort(itf, itf + dim, [](const Item &a, const Item &b) { return a.active < b.active; });
}

int main()
{
    Item arr[5] = {{0, 1}, {1, 2}, {0, 3}, {1, 4}, {1, 5}};
    int size = 5;
    for (int i = 0; i < size; i++)
    {
        cout << "id = " << arr[i].id << " => " << arr[i].active << endl;
    }

    cout << "After Sorting" << endl;

    SortByStat(arr, size);
    for (int i = 0; i < size; i++)
    {
        cout << "id = " << arr[i].id << " => " << arr[i].active << endl;
    }
}