我有一个2D数组,我希望在其中找到特定列的下限。
如何使用std::lower_bound
?
答案 0 :(得分:3)
将列标识粘贴到谓词中并使用外部数组的迭代器的简单答案。这假设一个二维数组,每行中有足够的列。当然,对于内置数组来说,确保数组不是很粗糙:
#include <algorithm>
#include <iostream>
int main()
{
int array[][3] = {
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 },
{ 10, 11, 12 }
};
for (int column(0); column < 3; ++ column) {
int (*lower)[3] = std::lower_bound(std::begin(array), std::end(array),
6, [=](int (&ptr)[3], int value){
return ptr[column] < value; });
std::cout << "column=" << column << " row=" << (lower - array) << "\n";
}
}
答案 1 :(得分:3)
这并不像人们想象的那么难,让我们首先介绍适用于范围的算法函数的摘要。
每个此类函数(如std::lower_bound
)都接受 begin 和 end 迭代器,以了解它们要搜索的元素。在我们的例子中的问题是,创建迭代遍历列而不是行的迭代器似乎并非易事。
好消息;它不是。
我们可以在 C ++ 中创建指向几乎所有内容的指针,这当然包括数组。
指针的好处在于,如果我们递增一个,我们将转到下一个元素,无论指针指的是什么类型。在我们的例子中,我们想迭代2D数组中的所有嵌套数组。
T a[5][3] = { ... };
T(*p)[3] = &a[0]; // is a pointer to an array of three `T`,
// currently pointing to a[0]
++p; // now referring to a[1]
#include <iostream>
#include <algorithm>
#include <iterator>
struct not_less_than_column {
not_less_than_column (unsigned long idx)
: m_idx (idx)
{ }
template<class T, unsigned long N>
bool operator() (T(&arr)[N], T const& needle) const {
return arr[m_idx] < needle;
}
unsigned long m_idx;
};
int main () {
int a[5][3] = {
{ 0, 24, 1 },
{ 0, 35, 1 },
{ 0, 42, 1 },
{ 0, 66, 1 },
{ 0, 100, 1 }
};
auto ptr = std::lower_bound (std::begin (a), std::end (a), 36, not_less_than_column (1));
for (auto const& e : *ptr)
std::cout << e << " "; // 0 42 1
}
注意:使用std::begin
和std::end
对&a[0]
和&a[5]
更加明确。
注意:我们可以用lambda替换not_less_than_column(1)
,但不支持通用lambdas C ++ 11 目前的方法更清晰。
答案 2 :(得分:1)
您可以尝试为列编写迭代器:
template<typename T , std::size_t ROWS , std::size_t COLUMNS>
class column_iterator
{
std::size_t _row; //Current position of the iterator
const std::size_t _column; //The column which the iterator traverses
T& _array[ROWS][COLUMNS]; //Reference to the array
public:
column_iterator( T (&array[ROWS][COLUMNS]) , std::size_t column , std::size_t pos = 0) :
_array{ array } ,
_row{ pos } ,
_column{ column }
{}
const T& operator*() const
{
return _array[_row][_column];
}
T& operator*()
{
return _array[_row][_column];
}
column_iterator& operator++()
{
_row++;
return *this;
}
friend bool operator==( const column_iterator& lhs , const column_iterator& rhs )
{
return lhs._row == rhs._row && lhs._column == rhs._column;
}
};
此外,您可以编写一个工厂函数来轻松创建此类迭代器:
template<typename T , std::size_t ROWS , std::size_t COLUMNS>
column_iterator<T,ROWS,COLUMNS> iterate_column( T (&array[ROWS][COLUMNS]) , std::size_t column , std::size_t row = 0 )
{
return column_iterator<T,ROWS,COLUMNS>{ array , row , column };
}
使用如下:
int main()
{
int foo[2][2] = { {1,2} ,
{3,4} };
auto iterator = iterate_column( foo , 0 );
}
甚至:
template<typename T , std::size_t ROWS , std::size_t COLUMNS>
column_iterator<T,ROWS,COLUMNS> column_begin( T (&array[ROWS][COLUMNS]) , std::size_t column )
{
return iterate_column( array , column , 0 );
}
template<typename T , std::size_t ROWS , std::size_t COLUMNS>
column_iterator<T,ROWS,COLUMNS> column_end( T (&array[ROWS][COLUMNS]) , std::size_t column )
{
return iterate_column( array , column , ROWS );
}
然后:
std::lower_bound( column_begin( foo , 1 ) , column_end( foo , 1 ) , 2 );
哪个(如果我已经正确实现了这个)应该返回2
答案 3 :(得分:1)
只需使用此功能:
vector<unsigned> column_lower_bound(const vector<vector<unsigned> >& matrix) {
size_t rows = matrix.size(), columns = matrix[0].size();
vector<unsigned> result(columns, ~0);
for(size_t y = 0; y < rows; y++) {
const vector<int>& curRow = matrix[y];
assert(curRow.size() == columns);
for(size_t x = 0; x < columns; x++) {
if(result[x] > curRow[x]) result[x] = curRow[x];
}
}
return result;
}
或类似的东西。如果必须,请将其设为模板。
只是为了感兴趣,这是C变种:
void column_lower_bound(size_t width, size_t height, unsigned (*matrix)[width], unsigned* result) {
for(size_t x = 0; x < width; x++) result[x] = ~0;
for(size_t y = 0; y < rows; y++) {
unsigned* curRow = matrix[y];
for(size_t x = 0; x < columns; x++) {
if(result[x] > curRow[x]) result[x] = curRow[x];
}
}
}
这在C ++中不起作用,因为你不能在C ++中使用具有运行时大小的2D数组。在这方面,C更灵活。
答案 4 :(得分:0)
由于一些答案已经告诉了如何去做,我建议使用二进制搜索为列创建我们自己的下界函数。
int lowerboundforcols(int target,int a[][m],int index)
{
//m are number of columns
//and index here is the index of the column for which you are searching.
int lo=0;int hi=n-1,ans=-1;
while(lo<=hi)
{
int mid=lo+(hi-lo)/2;
if(a[mid][index]<target)
{
lo=mid+1;
}
else{hi=mid-1;ans=mid;}
//because if there are duplicate 'target' and we want to
//find the first one.
}
return ans;
//returns -1 if there is no number greater than or equal to target
//in column,else return the first (0-based)index.
}