displaing the first elements of set - c++

I try to display the first elements of a std::set. For each time I would like to display the remaining elements.
For example a set: 4 6 8 9.
the first element is 4 the rest of the set is 6 8 9.
the first two elements are 4 6 the rest is 8 9.
then the first three elements are 4, 6, 8 the rest: 9.
The code I begun with:
for (std::set<int>::iterator it = my_set.begin(); it != my_set.end(); ++it)
{
std::vector<decltype(*it)> items((my_set.begin()), *it);
// items is a vector containing successively the n first elements
}
With this code I have errors and I can't have the rest of the set after displaying the first elements.
Can you help me?

The vector constructor you are looking for is the one taking iterators:
std::vector<std::decay_t<decltype(*it)>> items(my_set.begin(), it);
But you don't need intermediate std::vector, you might directly work with the range (with iterators)
You might use something like:
template <typename IT>
void print(IT begin, IT end)
{
const char* sep = "";
for (auto it = begin; it != end; ++it) {
std::cout << sep << *it;
sep = ",";
}
}
int main()
{
std::set<int> s{4, 6, 8, 9};
for (auto it = std::next(s.begin()); it != s.end(); ++it) {
std::cout << "First elements: "; print(s.begin(), it);
std::cout << ", Rest: "; print(it, s.end()); std::cout << std::endl;
}
}
Demo

If you want independent functions for N first elements and the rest:
#include <set>
#include <iostream>
using namespace std;
template<typename T>
void printHead(set<T>& mySet, unsigned int position) {
for (auto it = mySet.begin(); it != next(mySet.begin(), position); it++) {
cout << *it << ' ';
}
cout << endl;
}
template<typename T>
void printTail(set<T>& mySet, unsigned int position) {
for (auto it = next(mySet.begin(), position); it != mySet.end(); it++) {
cout << *it << ' ';
}
cout << endl;
}
int main(void) {
set<int> foo{0, 1, 2, 3, 4, 5, 6, 7};
const auto N = 3;
cout << "First " << N << " elements: ";
printHead(foo, N);
cout << "The rest: ";
printTail(foo, N);
}

Related

How do I properly use a range-based for loop for an std::array

I can iterate through the array with a traditional for loop and a traditional for loop with iterators, but when I try to use a ranged-based for loop, I do not get the same result.
#include <iostream>
#include <array>
int main() {
std::array<int, 5> ar = {1, 2, 3, 4, 5};
for(int i = 0; i < 5; i++) {
std::cout << ar[i] << " ";
}
std::cout << std::endl;
for(std::array<int, 5>::const_iterator it = ar.begin(); it != ar.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
for(const int& i: ar) {
std::cout << ar[i] << " ";
}
std::cout << std::endl;
}
1 2 3 4 5
1 2 3 4 5
2 3 4 5 0
In range-based for loop for(const int& i: ar), i refers to element but not index. So
for(const int& i: ar) {
std::cout << i << " ";
}

How can i insert multiple different values in single position of list in c++?

This code is from
geeksforgeeks
list<int> list1;
list1.assign(3, 2);
list<int>::iterator it = list1.begin();
advance(it, 2);
list1.insert(it, 5);
cout << "The list after inserting"
<< " 1 element using insert() is : ";
for (list<int>::iterator i = list1.begin();
i != list1.end();
i++)
cout << *i << " ";
cout << endl;
list1.insert(it, 2, 7);
cout << "The list after inserting"
<< " multiple elements "
<< "using insert() is : ";
for (list<int>::iterator i = list1.begin();
i != list1.end();
i++)
cout << *i << " ";
cout << endl;
It shows the output like this:-
The list after inserting 1 element using insert() is : 2 2 5 2
The list after inserting multiple elements using insert() is: 2 2 5 7 7 2
So, I want to add different values in a single position than the duplication of the same value. Is that even possible?
for ex- inserting 1,3,7 in 3rd position of the list.
Check the reference.
You can use one of insert():
template< class InputIt >
void insert( iterator pos, InputIt first, InputIt last); (until C++11)
template< class InputIt >
iterator insert( const_iterator pos, InputIt first, InputIt last ); (since C++11)
Example:
#include <iostream>
#include <vector>
#include <list>
int main(void) {
std::list<int> list1 = {2, 2, 5, 2};
std::vector<int> to_insert = {1, 3, 7};
std::cout << "before insert:";
for (int v : list1) std::cout << ' ' << v;
std::cout << '\n';
list1.insert(std::next(list1.begin(), 2), to_insert.begin(), to_insert.end());
std::cout << " after insert:";
for (int v : list1) std::cout << ' ' << v;
std::cout << '\n';
return 0;
}
Output:
before insert: 2 2 5 2
after insert: 2 2 1 3 7 5 2

C++: print out vector elements in a set container

I want to print out the vector element in a set container. I did the code as follows:
int main() {
vector<int> aa = {3, 2, 1, 1};
vector<int> bb = {5, 1, 7, 9};
set<vector<int>> myset; // setVector
myset.insert(aa);
myset.insert(bb);
for (auto elem : myset) {
cout << elem << ", ";
}
return 0;
}
However, this code can not print out the vector: (3, 2, 1, 1) and (5, 1, 7, 9).
you should also loop your vector elements inside myset.
for (auto const &elem : myset) { // loop set elements
for (auto const &v: elem) { // loop vector elements
std::cout << v << ", "; // print each vector element
}
std::cout << std::endl;
}
auto elem: myset here elem refers to the vectors.
to print out the contents of the vectors do this:
for (auto elem : myset)
{
for(auto x:elem) // elem is each vector
{
std::cout << x << " ";
}
std::cout << std::endl;
}
Here you iterate over the vectors in the inner for loop.
Also, you might want to use auto& in the loop if you are updating elements or to prevent copies since then you get a reference.
In order to print which you tried. You should overload << operator.
Also you may use like this.
for (auto elem : myset) {
cout << "(";
for(auto item:elem)
{
cout << item << ",";
}
cout << ")";
cout << endl;
}

C++ printing a list of sets

I'm trying to print out a list of sets but I'm confused with the syntax. I want each set to be on a new line. Here is my code:
set<int> set1 = { 2, 4, 5 };
set<int> set2 = { 4, 5 };
list<set<int>> list1;
list<set<int>>::iterator it = list1.begin();
list1.insert(it, set1);
list1.insert(it, set2);
cout << "List contents:" << endl;
for (it = list1.begin(); it != list1.end(); ++it)
{
cout << *it; //error is here
}
I'm getting an error when trying to print the pointer to the iterator. Pretty sure its because I'm using a set inside of the list, but I don't know the proper syntax for outputting this list.
Do you want to print as following?
for (it = list1.begin(); it != list1.end(); ++it)
{
for (set<int>::iterator s = it->begin(); s != it->end(); s++) {
cout << *s << ' ';
}
cout << endl;
}
output:
List contents:
2 4 5
4 5
There is no overload of operator << for std::set, you have to write the loop yourself (and possibly creating a function for that)
With for range, you may simply do:
for (const auto& s : list1) {
for (int i : s) {
std::cout << i << ' ';
}
std::cout << std::endl;
}

Print adjacency list by using multimap c++

I constructed an adjacency list based on the following link: Adjacency list
struct Node
{
string name;
int id;
};
typedef std::multimap<Node,Node> Graph;
Graph g;
g.insert (Graph::value_type(node1, node3));
g.insert (Graph::value_type(node1, node4));
g.insert (Graph::value_type(node1, node5));
g.insert (Graph::value_type(node2, node6));
g.insert (Graph::value_type(node3, node6));
How can I print the multimap by following the structure of the following image (Adjacency list)?
Graph::const_iterator it = g.begin();
while (it != g.end())
{
std::pair<Graph::const_iterator, Graph::const_iterator> range
= g.equal_range(it->first);
std::cout << it->first << ": "; // print vertex
for (; range.first != range.second; ++range.first)
{
std::cout << range.first->second << ", "; // print adjacent vertices
}
std::cout << std::endl;
it = range.second;
}
Output:
1: 3, 4, 5,
2: 6,
3: 6,
4: 7,
5: 7, 8, 9,
9: 5,
DEMO
If you don't want that redundant equal_range call, you can operate with a single iterator as long as two adjacent elements are equal in terms of ordering:
Graph::key_compare cmp = g.key_comp();
Graph::const_iterator it = g.begin(), itEnd = g.end(), prev;
while (it != itEnd)
{
std::cout << it->first << ": "; // print vertex
do
{
std::cout << it->second << ", "; // print adjacent vertices
prev = it++;
}
while (it != itEnd && !cmp(prev->first, it->first));
std::cout << std::endl;
}
DEMO 2
The following alternative solution makes use of C++11's range-based for loop. It iterates through all entries regardless the source node, and compares the current source node with the previous one. If they're different, start a new line in the output.
Compared to the solution using equal_range, this alternative is a little bit more cache-friendly: it only iterates over the whole graph once in the order of the nodes. equal_range first searches for the end of the range with the same source node, and then the loop iterates again over these elements. My alternative solution avoids this. (Of course, I did no benchmark and this is not to be meant as the ultimate fastest solution, but I just wanted to provide an alternative.)
std::ostream& operator<<(std::ostream& os, const Graph& g)
{
auto prev = g.begin()->first;
os << prev << ": ";
for (auto e : g) {
if (e.first < prev || prev < e.first)
os << std::endl << (prev = e.first) << ": ";
os << e.second << ", ";
}
return os << std::endl;
}
Live demo
If you implement operator!= for your Node type, the if-line can be simplified to a more readable comparison:
std::ostream& operator<<(std::ostream& os, const Graph& g)
{
auto prev = g.begin()->first;
os << prev << ": ";
for (auto e : g) {
if (e.first != prev) // <--- now more readable
os << std::endl << (prev = e.first) << ": ";
os << e.second << ", ";
}
return os << std::endl;
}