C++中的指针排序数组

Sorting Array of Pointers in C++

本文关键字:排序 数组 指针 C++      更新时间:2023-10-16

希望我能得到一些关于我所做排序方法的建议。

此代码的目的是创建一个int指针数组,并根据常规int数组的内容对该数组中的指针进行排序。然后根据原始int数组的位置为不同的变量赋值。

我对这段代码感到奇怪的是,据我所知,测试代码不应该影响任何事情。。。实际上是在影响我的指针内容。也许值没有改变,但我编写测试代码的方式导致了错误。

 //create array
 int c[8] = {3,1,5,7,8,2,6,4};
 //create pointer array
 int *newptr[8];
 for(int k = 0; k<8; k++)
 {
     newptr[k] = &c[k];
 }
//sort pointer array
for(int j = 0; j<8; j++)
{
    for(; j > -1 && *newptr[j] < *newptr[j+1]; j--)
    {
        int *temp = newptr[j+1];
        newptr[j+1] = newptr[j];
        newptr[j] = temp;
    }
}
//set lookuplocation
int lookuplocation;
for(int i = 0; i<8; i++)
{
    cout << *newptr[i];
    if(newptr[i] == &c[0])
    {
        cout << *newptr[i] << endl;
        //If I use endl or n to test the pointers values I end up with only
        //a part of the correct data. 
        cout << "nSuccess!n";
        lookuplocation = 0;
    }
}
//Also for my last test sometimes the first element gets messed up as well
//test arrays
for(int k = 0; k<8; k++)
{
    cout << "Element " << k << ": " << *newptr[k] << endl;
    cout << "Element " << k << ": " << newptr[k] << endl;
}

我认为有人可能真的需要以一种合理的方式对指针数组进行排序:

#include <iostream>
#include <array>
#include <algorithm>
int main() {
    std::array<int, 8> arr { 3, 5, 4, 1, 2, 7, 6, 8 };
    std::array<int*, 8> p_arr;
    for (unsigned i = 0; i < 8; ++i) {
        p_arr[i] = &arr[i];
    }
    std::sort(p_arr.begin(), p_arr.end(), [](int* a, int* b) { return *a < *b; });
    for (auto i : p_arr) 
        std::cout << *i;
}

丑陋的中间循环完全可以被超过zip映射范围的范围所替代,但我现在没有自己的带有引用语义的实现,而且我也懒得检查Boost1

这是科利鲁的活样本。

此外,因为我认为我们应该一遍又一遍地重复这一点,直到新手理解为止:

  • 不要重新发明分拣轮(除非是玩具实现)
  • 如果可能的话,尽量避免在C++中使用指针

1为了确保两个范围(在这种情况下是两个数组)具有相同的长度,这实际上很重要。不同的压缩约定要么要求范围具有相同的长度(崩溃或抛出),要么在其中一个范围太短时填充空数据。虽然在这样一个简单的程序中看起来很明显,但在现实世界的代码中要小心。

如果您的数组c[n]的范围为[1..n],您可以使用以下算法,该算法适用于O(n)时间复杂性:

for(int j = 0; j < n; j++)
    while(*newptr[*newptr[j] - 1] != *newptr[j])
        std::swap(newptr[*newptr[j] - 1], newptr[j]);

其背后的思想是将值1分配给指针newptr[0],将值2分配给指针newptr[1]。。。,以及n到指针CCD_ 5。没有比这更有效的算法了(尤其是在C++11中,因为std::swap将使用std::move)。

因此,对于int c[8] = {3,1,5,7,8,2,6,4},您得到(忽略对值表的引用):

1233

成功
45678


更新:如果您想要相反的顺序:

for(int j = 0; j < n; j++)
    while(*newptr[n - *newptr[j]] != *newptr[j])
        std::swap(newptr[n - *newptr[j]], newptr[j]);

对于int c[8] = {3,1,5,7,8,2,6,4},您可以得到:

8765433

成功
21

流行的方法是实现通用的sort函数,该函数使用给定的比较器对元素进行排序,因此可以对数组元素进行抽象。有一些方法:

template<typename ElementType, typename CompType>
void sort(ElementType array[], size_t size, CompType cmp);
template<typename ElementType, typename CompType>
void sort(std::vector<ElementType> & array, CompType cmp);
template<typename IteratorType, typename CompType>
void sort(IteratorType first, IteratorType last, CompType cmp);

最后一种方式更可取,因为您也可以抽象容器类型。

首先更改此项:

for(; j > -1 && *newptr[j] < *newptr[j+1]; j--)

进入

for(int i=j; i > -1 && *newptr[i] < *newptr[i+1]; i--)

它似乎更有效率。。

void sortList(int* list, const size_t &len)
{
    for(size_t i = 0; i < len; ++i)
    {
        for (size_t j = i+1; j < len; ++j)
        {
            if (list[i] > list[j])
            {
                std::swap(list[i], list[j]);
            }
        }
    }
}