4

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

此代码的目的是创建一个 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;
}
4

5 回答 5

10

我想有人可能实际上需要以一种理智的方式对指针数组进行排序:

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

丑陋的中间循环完全可以被超过 pp 范围的范围替换zip,但我现在没有自己的引用语义实现,我懒得去检查 Boost 。1

这是 Coliru 上的实时样本

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

  • 不要重新发明排序轮(除非它是一个玩具实现)
  • 如果可能,尽量避免在 C++ 中使用指针。

1这实际上很重要,以确保两个范围(在本例中为两个数组)具有相同的长度。不同的压缩约定要么要求范围具有相同的长度(否则会崩溃或抛出),或者如果其中一个范围太短,则填充空数据。虽然在这样一个简单的程序中看起来很明显,但在实际代码中要小心。

于 2013-08-05T11:52:03.730 回答
3

如果您的数组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分配给指针newptr[n-1]。没有更有效的算法(尤其是在 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

于 2013-08-05T08:07:13.767 回答
1

流行的方法是实现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);

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

于 2013-08-05T11:36:10.477 回答
0

首先改变这个:

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

进入

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

好像效率高很多。。

于 2013-08-05T07:13:46.737 回答
0
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]);
            }
        }
    }
}
于 2020-12-25T05:46:43.387 回答