在矩阵中打印唯一行

时间:2018-03-31 09:31:49

标签: c++ dictionary

我试图在地图的帮助下解决这个问题。我是Map的新手,但我不确定我的地图逻辑是否可以扩展为字符串?

`void findUniqueRows(int M[R][C])

map<int,string> m;
for(int i=0;i<R;i++)
{  
    string str="";
    for(int j=0;j<C;j++)
         str+=M[i][j];
         m.insert(i,str);
     `}

for (std::map<int,string>::iterator it=m.begin(); it!=m.end(); ++it)
std::cout << it->first << " => " << it->second << '\n';

}“

基本上我正在尝试使用int创建map作为行no和string作为该行的所有数组元素的串联。 现在对于下一行,同样的事情发生但如果当前字符串与地图中的现有字符串匹配,则不会插入。因此我的地图将包含唯一的行。 我是对的吗?

2 个答案:

答案 0 :(得分:1)

不,你的方法不正确。 std::map不关心它存储的键/值对的第二项内容。它只查看第一项。如果它已存在于地图中,则具有相同键的后续insert()将不会更改地图。所以在:

for (int j=0; j < C; j++) {
    str += M[i][j];
    m.insert(i, str);
}

j == 0时,对insert()的调用将成功,但该循环中的任何后续调用都不会执行任何操作。

使用地图根本无法解决这个问题,除非您的输入数组很大并且您需要一个比O(R²)快的算法。我会保持简单并使用以下方法:

for (int i = 0; i < R; i++) {
    bool duplicate = false;

    // Check if we have seen this row before
    for (int j = 0; j < i - 1; j++) {
        // Are the contents of row i equal to those of row j?
        if (memcmp(M[i], M[j], C * sizeof **M)) {
            duplicate = true;
            break;
        }
    }

    // If not, print it
    if (!duplicate) {
        for (int k = 0; k < C; k++)
            std::cout << M[i][k] << " ";
        std::cout << "\n";
    }
}

如果您确实想要使用类似地图的方法,则应使用std::set代替。这是一个可能的例子:

// Function to compare two rows
auto compare_row = [](int *a, int  *b){
    return memcmp(a, b, C * sizeof *a) < 0;
};

// A set that stores pointers to rows, using the above comparison function
std::set<int *, decltype(compare_row)> myset(compare_row);

// Insert all rows into the set
for (int i = 0; i < R; i++)
    myset.insert(M[i]);

// Print contents of the set
for (auto &&row: myset) {
    for (int k = 0; k < C; k++)
        std::cout << row[k] << " ";
    std::cout << "\n";
}

上面的示例只存储指向原始数组的指针,因此它非常节省空间。请注意,该集合现在基于比较函数进行排序,因此结果不一定与输入数组的顺序相同。要保持相同的顺序,您需要检查insert()调用的结果,并仅在插入成功时打印:

for (int i = 0; i < R; i++) {
    if (myset.insert(M[i]).second) {
        // print row i
    }
}

答案 1 :(得分:0)

使用std::map的方法可以看作示范程序中显示的内容。

#include <iostream>
#include <algorithm>
#include <map>
#include <iterator>

int main() 
{
    const size_t M = 5;
    const size_t N = 6;
    int a[M][N] = 
    {
        { 1, 1, 1, 1, 1, 1 },
        { 1, 1, 1, 1, 1, 0 },
        { 1, 1, 1, 1, 0, 0 },
        { 1, 1, 1, 1, 1, 0 },
        { 1, 1, 1, 1, 1, 1 }
    };

    auto comp = []( const int ( *a )[N], const int ( *b )[N] )
    {
        return std::lexicographical_compare( 
            std::begin( *a ), std::end( *a ), 
            std::begin( *b ), std::end( *b ) );
    };

    std::map<const int(*)[N], size_t, decltype( comp )> m( comp );

    for ( const int ( *row )[N] = a; row != a + M; ++row )
    {
        ++m[row];
    }

    for ( const auto &p : m )
    {
        if ( p.second == 1 )
        {
            std::cout << '[' 
                      << std::distance( std::cbegin( a ), p.first ) 
                      << "]: ";
            for ( int x : *p.first ) std::cout << x << ' ';
            std::cout << std::endl;
        }
    }

    return 0;
}

它的输出是

[2]: 1 1 1 1 0 0 

实际上,索引等于2的行是唯一的行。