【问题标题】:row and column of an index above of the main diagonal of the matrix (n * n)矩阵主对角线上方索引的行和列 (n * n)
【发布时间】:2022-01-11 15:21:24
【问题描述】:

正如您在图像中看到的,我从 0 开始索引了矩阵 (n * n) 主对角线上方的所有项目。我需要一种算法来获取该索引并为我们提供行和列。我用 c++ 编写了一个代码,它可以正常工作,但是,我想知道是否有任何更智能/更简单的算法来找到结果。谢谢。

我的代码:

int inputIndex = 8;
int n = 5;

int row = 0, column = 0;
for (int i = 0; i < n - 1; ++i) {
    if (inputIndex < n - i - 1){
        row = i;
        column = inputIndex + i + 1;
        break;
    }
    inputIndex -= n - i - 1;
}

cout << "row = " << row << endl << "column = " << column;

输出:

row = 2
column = 4

【问题讨论】:

标签: c++ algorithm matrix


【解决方案1】:

不一定更容易,但您可以在编译时计算所有映射 然后也在运行时使用它们。这意味着至少 for 循环不必一遍又一遍地运行。

#include <array>
#include <stdexcept>
#include <limits>
#include <iostream>

// put this in a header file
namespace details
{

    // create a structure to hold row/col data this allows 
    // those two values to be returned from one function call.
    struct position_t
    {
        position_t() = default;

        constexpr position_t(const std::size_t r, const std::size_t c) :
            row{ r },
            col{ c }
        {
        }

        std::size_t row = 0;
        std::size_t col = 0;
    };

    // function to compare two position_t structs, used later in static_assert.
    // constexpr means the compiler can call this function at compile time.
    constexpr bool operator==(const position_t& lhs, const position_t& rhs)
    {
        return ((lhs.row == rhs.row) && (lhs.col == rhs.col));
    }

    // template class based on the size of the matrix
    // this class will store precalculated mappings from index to position and the 
    // other way around.
    template<std::size_t N>
    class index_map_t
    {
    public:

        // allow class to be instantiated at compile time 
        constexpr index_map_t() :
            m_to_pos{},
            m_to_index{}
        {
            std::size_t index{ 0ul };
            for (std::size_t row = 0; row < N; ++row)
            {
                for (std::size_t col = 0; col < N; ++col)
                {
                    // row by row the index is increased only
                    // if the column value is greater then the row value
                    // (the upper right half of the matrix)
                    if (col > row)
                    {
                        // store valid position/index values in internal arrays
                        // std::array can be used in constexpr
                        m_to_pos[index] = position_t{ row, col };
                        m_to_index[row][col] = index;
                        index++;
                    }
                    else
                    {
                        // for positions in the lower left half fill in "invalid" indices
                        // so we can detect them.
                        m_to_index[row][col] = std::numeric_limits<std::size_t>::max();
                    }
                }
            }
        }

        // convert a position to an index.
        constexpr auto to_index(const std::size_t row, const std::size_t col) const
        {
            if ((row >= N) || (col >= N)) throw std::invalid_argument("position out of range");

            if (m_to_index[row][col] == std::numeric_limits<std::size_t>::max())
            {
                throw std::invalid_argument("no inverse lookup for this position, position is not in upper-right half of matrix");
            }

            return m_to_index[row][col];
        }

        // convert an index to a position_t
        constexpr auto to_position(const std::size_t i) const
        {
            return m_to_pos[i];
        }

    private:
        // for this N*N sparse matrix type there will be 2*N valid indices
        std::array<position_t, 2 * N> m_to_pos;                 

        // the inverse mapping is a bit less memory efficient and
        // will be an N*N array.
        std::array<std::array<std::size_t, N>, N> m_to_index;
    };

} // details

int main()
{
    // calculate mapping at compile time for a 5x5 matrix
    // you can use this as member in your matrix class
    constexpr details::index_map_t<5> remapping;

    // this means we can even check the calculations at compile time
    static_assert(remapping.to_position(0) == details::position_t{ 0,1 });
    static_assert(remapping.to_position(1) == details::position_t{ 0,2 });
    static_assert(remapping.to_position(2) == details::position_t{ 0,3 });
    static_assert(remapping.to_position(3) == details::position_t{ 0,4 });
    static_assert(remapping.to_position(4) == details::position_t{ 1,2 });
    // etc..

    static_assert(remapping.to_index(1, 3) == 5);
    static_assert(remapping.to_index(3, 4) == 9);

    // runtime code
    auto pos = remapping.to_position(5);
    std::cout << "The position for index 5 : row = " << pos.row << ", col = " << pos.col << "\n";
    return 0;
}

【讨论】:

  • 感谢您的努力。
  • 不客气 :) 如果您有任何问题,请告诉我
猜你喜欢
  • 2017-10-14
  • 1970-01-01
  • 2021-11-15
  • 1970-01-01
  • 1970-01-01
  • 2017-11-16
  • 1970-01-01
  • 2015-01-15
  • 2017-08-05
相关资源
最近更新 更多