如何使向量中的索引成为一对(x,y)坐标?

时间:2018-08-12 07:06:12

标签: c++ c++11 vector stl

#include<bits/stdc++.h>
using namespace std;

int main() {

     int i,j;
     vector<int> v(100);   // defined a vector of size 100

     for(i=1;i<=50;i++) {
         v[i]=i;             // storing the values as we do in 1-d array
     }

    for(int i=1;i<=50;i++) {

         cout<<"index="<<i<<" "<<v[i]<<"\n";  // It will give output similar 
                                               //   to 1-d array
    }
    return 0;
}

因此是一维向量的情况,其中向量的索引是整数,并且值也是整数。上面的代码运行良好。

但是我想将向量的索引作为对(i,j),并将值作为整数。

有关更多说明,请参见下面的代码。

    #include<bits/stdc++.h>
    using namespace std;

    int main() {

         int i,j;

         vector<pair<int,int>> ve(make_pair(100,100));   
         //defined a vector of size of indices (100,100)

         for(i=1;i<=50;i++) {

               for(j=0;j<=50;j++) {

                  ve[make_pair(i,j)]=2; // Storing value of 2 in all the 
                                        // (i,j) indices
              }
         }

        for(int i=1;i<=50;i++) {

             for(j=0;j<=50;j++) {

                  cout<<ve[make_pair(i,j)]<<" "; 
                  // Output should be 2 in all the possible pairs of (i,j)
             }
        }
        return 0;
    }

但是上面的代码不起作用:(。 请告诉我如何解决此问题。

5 个答案:

答案 0 :(得分:2)

向量与数组一样,仅适用于整数索引。对于矢量vec,索引必须必须在0 <= index < vec.size()范围内,否则它要么不能编译(不能转换为unsigned int),要么行为不确定(超出范围) 。

您已写

vector<pair<int,int>> ve

这意味着您将创建一个包含对的向量,而不是按对进行索引。

现在,如果要使用二维向量(即矩阵),则应检查Boost matrix。您也可以自己实现它,但是使其通用将需要一些努力。基本思想是将对转换为单个整数值。最简单的实现是:

template <class T>
void init_2d(std::vector<T> &vec, std::pair<unsigned, unsigned> coordinates)
{
    vec.resize(coordinates.first * coordinates.second);
}
inline unsigned flatten(std::pair<unsigned, unsigned> coordinates,
            unsigned num_columns)
{
    return coordinates.first * num_columns + coordinates.second;
}

template <class T>
T & get_2d(std::vector<T> & vec, 
       std::pair<unsigned, unsigned> coordinates,
       unsigned num_columns)
{
    return vec.at(flatten(coordinates, num_columns));
}
template <class T>
const T & get_2d(const std::vector<T> & vec, 
         std::pair<unsigned, unsigned> coordinates,
         unsigned num_columns)
{
    return vec.at(flatten(coordinates, num_columns));
}

,然后在您的代码中使用它:

int main() {

    std::vector<int> ve;
    auto dimensions  = std::make_pair(100,100);
    init_2d(ve, dimensions);

    for(int i=1;i<=50;i++) {
       for(int j=0;j<=50;j++)
         get_2d(ve, {i,j}, dimensions.second) =j; 
    }

    for(int i=1;i<=50;i++) {
        for(int j=0;j<=50;j++)
            std::cout << get_2d(ve, {i,j}, dimensions.second) <<" "; 
        std::cout << '\n';
    }
    return 0;
}

但是,与其重新实现现有代码,不如使用Boost矩阵。如果您想学习如何实现矩阵(这是一个很好的主意),请继续尝试将上述函数和向量转换为一个类,并将dimensions对放入该类中。对于矩阵,拥有一个类比使用单独的函数要好。与单独的函数相比,维护类的不变性更容易。

请注意:您可以改用std::map<std::pair<int, int>>,但是遍历它会更加困难,并且速度会慢很多。如果可以使代码更清晰,则使用std::map是个好主意,但与std::map<pair<...>> + _2d函数相比,std::vector是否更易于使用尚不清楚。

答案 1 :(得分:1)

我建议您改用map

Operator [] for mapkey_type作为参数,这是一个容器,这意味着您可以使用pair对象作为索引(在地图中称为键),但是Operator [] for vetor则以{{1 }}作为无符号整数的参数。

您的代码可能如下所示:

size_type

答案 2 :(得分:1)

保持简单

您需要的只是 1 (一个!)C ++行:... +更新:可选宏(该宏用于回答@eneski注释):

std::vector<std::vector<int>> ve(100, std::vector<int>(100, 0)); // Initialize to 0

// Turns [wr(pair)] syntax to [pair.first][pair.second] syntax:
#define wr(pr) (pr).first][(pr).second // Wrapper macro

比使用:

ve[wr(std::make_pair(i, j))] = 35; // For example  
int val = ve[wr(std::make_pair(i, j))];
// Or:
ve[i][j] = 70; // For example
val = ve[i][j];

真正不需要使用wr包装宏。使用ve[i][j],如果代码中有std::pair p,请使用:ve[p.first][p.second]而不是ve[p]-两者相同。另外,采用(i, j)并即时进行make_pair 只是再次将它们用作[i][j]索引是胡说八道。如果仍然坚持使用语法,则使用wr包装宏。

-

但是,在固定顺序范围内,二维std :: array是一个更好的选择(并且,如果您坚持,也可以添加包装宏):

#include <array>

int main()
{
    int i = 7, j = 5;

    std::array<std::array<int, 100>, 100> ar; // 100 X 100
    ar[0].fill(0); ar.fill(ar[0]); // Initialize to 0

    ar[i][j] = 35; // For example

    return 0;
}

答案 3 :(得分:1)

另一种解决方案:通过聚合一个标准容器来创建自己的容器。

极端简化的示例:

public int getKey(String s){
 int [] arr=countLetters(s);
 int maxDex=indexOfMax(arr);
 int key;
 if (maxDex<4) key= maxDex-4+26;
 else key=maxDex-4;
 return key;
 }

答案 4 :(得分:0)

您是否只是试图像访问2D向量一样访问1D向量内容?也许您可以使用辅助函数将2d索引转换为1d索引,例如:

#include <vector> 
#include <iostream>
#include <cassert>

template<size_t ROWS, size_t COLS>
size_t convertIndex(size_t row, size_t col)
{
    assert(row < ROWS && col < COLS);
    return row * COLS + col;
}

int main() 
{
    std::vector<int> v =
    {
        0,1,2,3,4,
        5,6,7,8,9
    };

    std::cout << v[convertIndex<2, 5>(1, 3)];
}

This输出8