I made an implementation of dfs in c++ by multimap container in this way:
multimap<int, int>g;
And we could add edges in the graph in this way:
g.insert(make_pair(1,2));
Now I'm going to implement the Khushkal Algorithm by multimap. But in this case I got one more extra data per node , the weight. So now I need to store, (1,2,3) for example , triple data in the multimap.
Then what will be the multimap declaration look like??
And how could I insert such nodes?
You will have to map an item on another item.
Pick what you would like to use as key. If you decide on one key and two values, you map an int on a pair of ints. You can also opt to use a pair as key and map it on an int.
If you just would like to store pairs or tuples of three items, it is better to use an (unordered)set of these data members.
Option 1:
multimap<int, pair<int,int>>
Option 2:
multimap<pair<int,int>,int>
Related
I came across a problem where I needed to store two values, one id and other its influence, and id should be randomly accessible. Also it should be sorted based on influence and if both influence are same , sort based on id. With these things in mind, I used map,but is there a way to actually do it ?
I tried below comparator and map but it gives error
struct cmp
{
bool comparator()(const pair<int,int>a,const pair<int,int>b)
{
if(a.second==b.second) return a.first<b.first;
else return a.second<b.second;
}
};
unordered_map<int,int,cmp>m;
From what I understand, you want a collection sorted by one value but quickly indexable by another. These two points are in contradiction. Sorting a collection by a key value makes it quicker to index by that key value. There is no easy way to make a collection quickly indexable in two different ways at the same time. Note that I say "quickly indexable" instead of talking about random access. That's yet a different concept.
In short, you need two collections. You can have a main one that stores influence-ID pairs and is sorted by influences, and a secondary one that stores IDs and maps them to the main collection. There are many options for that; here is one:
std::set<std::pair<int,int>> influences;
std::unordered_map<int, decltype(influences)::iterator> ids;
When inserting an influence-ID pair, you can insert into influence first and then take the iterator to that new element and insert it with the ID.
Another solution is to keep a main collection of influence-ID pairs but this time sorted by IDs (and binary search it when you need to get the influence from an ID), and maintain a array of permutation indices that tells you at what index an element of the main collection would be if it were sorted by influence. Something like this:
std::vector<std::pair<int,int>> influences;
// insert all elements sorted by ID
std::vector<decltype(influences)::size_type> sorted_indices;
// now sort by influences but modifying `sorted_indices` instead.
Relevant question
If the IDs are all from 0 to N, you can even just have influences indexed by ID:
std::vector<int> influences; // influences[id] is the influence value corresponding to id
This gives you random access.
The "correct" choice depends on the many other possible constraints you may have.
I have a map that maps strings to vectors of strings:
std::unordered_map<std::string, std::vector<std::string>>> myMap;.
Is there a nice way (as little code as possible while still being readable) to append a value to the vector of a given key?
How to handle the case of adding a value to a vector for a new key for which the vector hasn't been initialized yet?
You want:
myMap["key"].push_back("string");
If the vector for this key doesn't exist, it will be created automatically.
I am trying to sort a map with definition map<double,deque<Object>>
with the maximum value of double (key) but by default the map takes the minimum value of key . How can I sort the map by the maximum value of key which is a double .
Thanks in advance
You can't re-sort a map, but you can use a map that sorts itself in the reverse order to the default. std::map has a third template parameter for the comparison functor used for ordering. The default is std::less<key_type>. You can trivially use the reverse ordering by using std::greater<key_type>:
std::map<double, std::deque<Object>, std::greater<double>> m;
The closest you can come to sorting a map is to create a new one based on an original with different sorting criteria:
std::map<double, std::deque<Object>> orig = ....;
std::map<double, std::deque<Object>, std::greater<double>> m(orig.begin, orig.end());
map is a key-value pair, key has to be unique in general, if not then value type could be a vector or list instead of a single typed elemental value like hash_map> where MyType is struct or a class. While querying you search with the key to retrieve the value, no notion of sorting. Otherwise, you need to use a vector instead.
I have a std::map with key_type and mapped_type. Every instance of mapped_type is inserted into the map as 3 copies - under 3 different key values. This allows me to retrieve the value based on any of the 3 keys.
But the drawback is that when I want to delete the item, I need to look for 3 keys instead of just one, in order to get rid of all 3 copies.
Is it possible to compose the 3 keys into one class and be able to compare such object with 1 key, while maintaing a strict weak ordering? In such scenario, how would the operator< look like for key_type?
EDIT: The 3 keys are of the same type e.g. a single record is accessible with 3 different integer values (and those key values are not used by any other record). So from what I understand Boost.MultiIndex is not a solution for this problem.
Use Boost.MultiIndex. See http://www.boost.org/doc/libs/1_49_0/libs/multi_index/doc/tutorial/basics.html#multiple_sort
I'd suggest using two data structures encapsulated into a single object:
std::list<Node> list;
std::map<Key, std::list<Node>::iterator> map;
where Node contains:
Value value;
and 3 instances std::map<Key, std::list<Node>::iterator>::iterator i1, i2, i3;
You can then insert and remove values with appropriate bookkeeping to ensure that the structures remain consistent.
I have some data with a key associated with each data item. The key is made of two parts: let's call them color and id. I want to iterate the container by color to speed up rendering and I also want to find items in the container by id alone.
I tried using std::map for this with a key
class MyKey {
public:
int color;
int id;
bool operator<(...)
bool operator==(...)
};
But I cannot provide a < operator that would keep the data sorted by color and at the same time allow map::find to work on id alone (i.e. no information about color).
I want both the insert and find operations to be fast (e.g. O(log(n))).
Any ideas what kind of container I could use to implement this?
Adapt the example here from Boost.Multi_index based on the following modifications:
typedef multi_index_container<
MyKey,
indexed_by<ordered_unique<identity<MyKey> >,
ordered_non_unique<member<MyKey,int,&MyKey::color> >
>
> DataSet;
Try Boost.BiMap, it's a map with 2 views.
Otherwise there is the more complicated Boost.MultiIndex.
If you'd rather write your own than use Boost (dumb in my opinion) you can make a class that holds two maps. One to map color and the other to map ID. The map values would be pointers. You'd define insert and find operations for your new class. The insert would new a data struct and insert the pointer into both maps. The find operations would locate the item using either map as appropriate. For delete/remove operations it is a little trickier: you'd need to look up the data struct by a map, then remove it from both maps, probably by using the data in the data struct to find the other map entry.