通过 std::sort 对 C 2D 数组进行排序
Sorting a C 2D array via std::sort
我有一个 2D 数组a[][40]
。我正在尝试通过调用std::sort
对其进行排序,并且我已经编写了Compare
函数。但是,C++
希望我有一个要排序的std::vector
,而不是一个简单的数组,我希望排序后的数组本身a
,我不想创建另一个数组并将排序结果保存在那里。似乎有很多方法可以实现这一点。我可以想到五种方法,但似乎没有一种是高效和有效的。
1(
直接使用
std::sort(std::begin(a), std::begin(a) + something, cmp);
它不起作用,因为std::begin
不知道如何指向 2D 数组的开头。此外,即使编译,它的排序也会不正确,因为 2D 数组不是对数组的引用数组,而是连续数组(与 Java 不同(。
游乐场:https://godbolt.org/g/1tu3TF
2(
std::vector<unsigned char[40]> k(a, a + x); std::sort(k.begin(), k.end(), cmp);
然后将所有内容复制回
a
它不起作用,因为它是一个 2D 数组,并且不能使用std::sort
以这种方式排序。与第一次试验相比,这个试验使用的内存是内存的两倍,并且复制了两次所有内容(如果它有效的话(!
游乐场:https://godbolt.org/g/TgCT6Z
3(
std::vector<int> k(x); for (int i = 0; i < x; k[i] = i, i++); std::sort(k.begin(), k.end(), cmp2);
然后将
a
的顺序更改为与k
相同;
这个想法很简单,创建一个代表性"指针"的向量,对它们进行排序(因为cmp2
函数秘密访问a
并比较值(,然后使a
与k
具有相同的顺序。
最后,重新排序循环将非常复杂,需要一个大的临时变量。此外,为了让cmp2
访问a
的值,必须创建一个指向a
的全局变量指针,这是"坏"代码。
游乐场:https://godbolt.org/g/EjdMo7
4(
对于所有
unsigned char[40]
,可以创建一个结构,并且可以将其值复制到结构中。需要声明比较运算符和=
运算符。排序后,可以将它们复制回a
。
如果数组不必复制到结构体以使用结构体的运算符,这将是一个很好的解决方案,但它们需要被复制,因此所有值将被复制两次,并且将根据需要使用两次内存。
5(
对于所有
unsigned char[40]
,可以创建一个具有指向它们的指针的结构。它们可以按指向的值排序,结果可以保存到指针数组中。
这可能是最好的选择,尽管结果是指针数组而不是a
。它为什么好的另一个原因是它不会移动数组,而是移动指针。
总而言之,我需要通过std::sort
对 2D 数组a[][40]
进行排序,但我还没有决定最佳方法。似乎有一个我想不出的"最好的方法"。你能帮帮我吗?
编辑:澄清一下,我希望{{3,2}{1,4}}
变得{{1,4}{3,2}}
问题不在于迭代 2D 数组。如果列大小是constexpr
值,则指向数组的指针是很好的迭代器。
但是C++排序(或变异(算法都要求底层类型是可移动的,并且移动可分配的,并且数组不可分配。但是包装底层数组就足够了:
template <class T, int sz>
class wrapper {
T* base;
bool own; // a trick to allow temporaries: only them have own == true
public:
// constructor using a existing array
wrapper(T* arr): base(arr), own(false) {}
~wrapper() { // destructor
if (own) {
delete[] base; // destruct array for a temporary wrapper
}
}
// move constructor - in fact copy to a temporary array
wrapper(wrapper<T, sz>&& src): base(new T[sz]), own(true) {
for(int i=0; i<sz; i++) {
base[i] = src.base[i];
}
}
// move assignment operator - in fact also copy
wrapper<T, sz>& operator = (wrapper<T, sz>&& src) {
for(int i=0; i<sz; i++) {
base[i] = src.base[i];
}
return *this;
}
// native ordering based on lexicographic string order
bool operator < (const wrapper<T, sz>& other) const {
return std::char_traits<char>::compare(base, other.base, sz) < 0;
}
const T* value() const { // access to the underlying string for tests
return base;
}
};
然后,您可以使用任何C++排序算法对 C 兼容的 2D 数组进行排序:
std::vector<wrapper<char, 40> > v { &arr[0], &arr[sz] }; // pointer are iterators...
std::sort(v.begin(), v.end()); // and that's all!
for (int i=0; i<sz; i++) { // control
std::cout << arr[i] << std::endl;
}
开销是包含指针和布尔值的结构向量,但排序的实际上是原始的 2D 数组。
当然,由于 C 库可以从C++访问,因此qsort
对 C 兼容的 2D 数组进行排序肯定会更容易。但是这种方式允许使用stable_sort
或partial_sort
(如果它们是相关的(。
- 2D数组来自文本输入,中间有空格
- 如何使用用户输入在C++中正确填充2D数组
- 如何在C++中检查2D数组中负值的输入验证
- 当我在main中声明了我的2d数组时,为什么我的程序会退出
- 如何将以逗号和空格分隔的整数读取到 2D 数组中?
- 如何在C++函数中声明静态 2D 数组?
- 如何声明一个可以在整个程序中使用的全局 2d 3d 4d .. 数组(堆版本)变量?
- 我已经阅读了很多关于 2d 数组的信息,但我在作业中使用它时遇到了麻烦
- 使用矢量将文本文件中的输入存储到 2D 数组中
- 获取 2D 数组 c++ 中的所有数字对
- 这是使用回溯的 nqueen 问题,但我使用了动态 2d 数组,我的程序编译良好,但不返回任何输出
- 如何在构造函数中使用初始值设定项设置具有相同值的 2d 数组?
- 在 Python 和 c++ 2d 数组初始化之间.这是怎麽?为什么呢?
- 如何打印 2D 字符数组C++
- 如何将数组 2d 作为参数从函数传递并返回数组 2d 此函数
- 数组 2D 多个值
- 创建数组数组 (2D),而无需在 Java 中初始化内部数组
- 如何在C++中将文本文件传输到数组2D
- 从同一类的另一个方法调用数组2D-C++
- 获取地址在数组2d中的位置