[英]How can I enter values into a map with a struct as key?
我有一個以struct
為鍵的映射,我重載了<
運算符,但映射將每個條目存儲為單獨的鍵,即使它們相同。 代碼如下:
#include <iostream>
#include <vector>
#include <map>
using namespace std;
struct vertex
{
int color;
vertex *pi;
int index;
bool operator<(const vertex & v ) const {
return this->index < v.index;
}
bool operator==(const vertex & v) const {
return this->index == v.index;
}
};
int main()
{
int x, y, num_edges;
vector<vertex* > v;
vertex *temp1, *temp2, *temp;
map<vertex*, vector<vertex*> > m;
map<vertex*, vector<vertex*> >::iterator it;
cout << "\nEnter no. of edges: ";
cin >> num_edges;
for( int i = 0; i < num_edges; i++ )
{
cout << "\nEnter source: ";
cin >> x;
cout << "\nEnter dest: ";
cin >> y;
temp1 = new vertex;
temp2 = new vertex;
temp1->index = x;
temp2->index = y;
m[temp1].push_back(temp2);
m[temp2].push_back(temp1);
}
temp1 = new vertex;
temp2 = new vertex;
cout << "\nPrinting map: " << endl;
for( it = m.begin(); it != m.end(); it++ )
{
temp = (*it).first;
cout << temp->index << "\t";
v = (*it).second;
for( int i = 0; i < v.size(); i++ )
{
temp1 = v[i];
cout << temp1->index << "\t";
}
cout << "\n";
v.clear();
}
for( it = m.begin(); it != m.end(); it++ )
{
temp = (*it).first;
v.push_back(temp);
}
return 0;
}
我現在得到的輸出是:
Enter no. of edges: 4
Enter source: 1
Enter dest: 3
Enter source: 4
Enter dest: 3
Enter source: 4
Enter dest: 2
Enter source: 2
Enter dest: 1
Printing map:
1 3
3 1
4 3
3 4
4 2
2 4
2 1
1 2
但它應該是:
1 3 2
2 4 1
3 1 4
4 3 2
我哪里錯了?
std::map 將比較您作為鍵( vertex*
)提供的類型,但您在頂點上定義<
運算符。
您可以使用結構本身作為鍵,或者 - 如果您必須使用指針 - 您必須為映射提供一種比較指針的方法。
現在, std::map
使用std::less
作為比較謂詞,它在<
therm 中定義(這就是為什么使用結構本身,您可以通過重載<
來實現結果)。
您可以:
o) 定義一個比較頂點*的謂詞:它可以是
template <class T> //assume T is a pointer or pointer-like class
struct redirected_less : public std::binary_function <T,T,bool>
{
bool operator() (const T& x, const T& y) const {return *x < *y;}
};
然后將您的地圖定義為
std::map<vertex*, vector<vertex*>, redirected_less<vertex*> >
o) 將頂點 * 的 std::less 特化為
namespace std
{
template <>
struct less<vertex*> : binary_function <vertex*,vertex*,bool>
{
bool operator() (vertex* x, vertex* y) const {return *x < *y; }
};
}
並將您的地圖聲明為
std::map<vertex*, vector<vertex*> >
照常。
我個人更喜歡第一個(提供更本地化的代碼,在以后的閱讀中更少“神秘”)
您不能使用指針作為鍵。 如果您有兩個結構,根據您的規則它們是“相同的”,但是它們是在堆上用new
分配的,那么它們的指針將永遠不會相同。
使用結構而不是它們的指針作為鍵。
map<vertex*, vector<vertex*> > m;// its key type vertex*
m 用途
bool operator < (vertex * const, vertex* const) ;
訂購時
所以你需要超載
bool operator < (vertex * const, vertex* const);
我們這里有問題。 我們不能重載指針。 我們可以像這樣提供我們自己的比較函數:
struct cmp{
bool operator ()(vertex * const first, vertex* const second)
{ return first.index < second->index;}
};
cmp _cmp;
map<vertex*, vector<vertex*>, cmp> m(_cmp);
Emilio Garavaglia 分析了您的代碼的問題以及如何很好地修復它。 但是,如果您可以使用C++11功能,那么您可以稍微現代化一下您的解決方案。 例如,您可以使用lambda 表達式而不是為您的結構定義operator<
,並將其傳遞給映射的構造函數。 如果您無法修改要存儲在地圖中的結構,或者您想為不同的地圖提供不同的比較函數,則此方法很有用。 基於范圍的for
循環使您不必處理迭代器,而占位符auto
您不必指定冗長的容器元素類型。 我還想提一下,您無需為地圖指定operator==
即可工作。
vertex
為鍵的解決方案為了清楚起見,我用硬編碼值替換了用戶輸入:
struct vertex {
int color;
vertex *pi;
int index;
};
int main() {
auto comp = [](const vertex& v1, const vertex& v2) { return v1.index < v2.index; };
std::map<vertex, std::vector<vertex>, decltype(comp)> m(comp);
// Replace user input.
std::vector<std::pair<int, int>> edges = { {1, 3}, {4, 3}, {4, 2}, {2, 1} };
// Fill the map.
for(auto const &e : edges) {
vertex temp1;
vertex temp2;
temp1.index = e.first;
temp2.index = e.second;
m[temp1].push_back(temp2);
m[temp2].push_back(temp1);
}
// Print the map.
std::cout << "Printing map:" << std::endl;
for (auto const &kv : m) {
std::cout << kv.first.index << " =>";
for (auto const &v : kv.second)
std::cout << " " << v.index;
std::cout << std::endl;
}
return 0;
}
輸出:
打印地圖:
1 => 3 2
2 => 4 1
3 => 1 4
4 => 3 2
注意:如果您可以使用C++17 ,那么您可以通過使用 結構化綁定進一步縮短打印地圖的代碼,如Coliru 上所示。
vertex*
為鍵的解決方案基本上,您必須用vertex*
替換上述代碼中所有出現的vertex
。 此外,您必須確保 lambda 表達式不比較給定的指針,而是指針所指結構的內容:
auto comp = [](const vertex* pv1, const vertex* pv2) { return pv1->index < pv2->index; };
std::map<vertex*, std::vector<vertex*>, decltype(comp)> m(comp);
您還必須確保在最后刪除所有動態分配的頂點。 例如,您可以通過以下方式正確清空地圖:
for (auto const &kv : m)
for (auto const pv : kv.second)
delete pv;
m.clear();
注意:為了簡化內存管理,您應該更喜歡在映射中存儲智能指針,例如std::unique_ptr
或std::shared_ptr
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.