查找2D数组中列的lower_bound()

时间:2014-06-07 12:50:51

标签: c++ stl

我有一个2D数组,我希望在其中找到特定列的下限。

如何使用std::lower_bound

执行此操作

5 个答案:

答案 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::beginstd::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.
 }