adjacency graph in c++ using stl - c++

I want to make adjacency list representation of graph using vector and when we declare vector as global variable where the memory is allocated to vector in stack or heap
#include<bits/stdc++.h>
#include<vector>
using namespace std;
void addedge(vector<int> &graph, int u, int v) {
graph[u].push_back(v);
graph[v].push_back(u);
}
void printgraph(const vector<int> &gph) {
for (int v = 0 : gph) {
cout << v;
for (auto x : gph[v]) {
cout << x;
printf("\n");
}
}
}
int main() {
vector<int> gph;
addedge(gph, 2, 3);
addedge(gph, 6, 7);
addedge(gph, 1, 2);
printgraph(gph);
}

gph is a vector of int so you cannot access the method push_back in graph[u] because graph[u] is a int!
You can imagine an adjacency list as a space efficient matrix(2D) of int where you can have rows of different sizes.
But ultimately it is a 2D structure.
This means you have to declare your adjacency list as a vector<vector<int>>.
The following code should give you some indication on how it works:
#include<iostream>
#include<vector>
using Graph = std::vector<std::vector<int>>;
void addedge(Graph &graph, const int u, const int v) {
graph[u].push_back(v);
graph[v].push_back(u);
}
void printgraph(const Graph &gph) {
for (int node = 0 ; node < gph.size() ; node++) {
std::cout<<node<<" : ";
for (auto x : gph[node]) {
std::cout << x << " ";
}
std::cout<<std::endl;
}
}
int main() {
Graph gph(8, std::vector<int>());
addedge(gph, 2, 3);
addedge(gph, 6, 7);
addedge(gph, 1, 2);
printgraph(gph);
}

Rather than having an explicit parameter of your adjacency list, you could collect the data and behaviour into a class. Depending on how sparse your graph is, there are various representations available. To contrast with Davide's answer, I'll use std::multimap<int, int>.
class Graph
{
std::multimap<int, int> edges;
public:
void addedge(int u, int v)
{
edges.insert(u, v);
edges.insert(v, u);
}
friend std::ostream& operator<<(std::ostream& os, const Graph & graph)
{
for (auto v_it = graph.begin(), v_end = {}; v_it != graph.end(); v_it = v_end)
{
v_end = graph.upper_bound(v_it->first);
os << v_it->first << " : ";
for (auto it = v_it; it != v_end; ++it)
{
os << it->second << " ";
}
os << std::endl;
}
return os;
}
}
int main() {
Graph gph;
gph.addedge(2, 3);
gph.addedge(6, 7);
gph.addedge(1, 2);
std::cout << graph;
}

Related

Sort just one member of the classes in a vector, leaving the other members unchanged

There are tons of answers for sorting a vector of struct in regards to a member variable. That is easy with std::sort and a predicate function, comparing the structs member. Really easy.
But I have a different question. Assume that I have the following struct:
struct Test {
int a{};
int b{};
int toSort{};
};
and a vector of that struct, like for example:
std::vector<Test> tv{ {1,1,9},{2,2,8},{3,3,7},{4,4,6},{5,5,5} };
I do not want to sort the vectors elements, but only the values in the member variable. So the expected output should be equal to:
std::vector<Test> tvSorted{ {1,1,5},{2,2,6},{3,3,7},{4,4,8},{5,5,9} };
I wanted to have the solution to be somehow a generic solution. Then I came up with a (sorry for that) preprocessor-macro-solution. Please see the following example code:
#include <iostream>
#include <vector>
#include <algorithm>
struct Test {
int a{};
int b{};
int toSort{};
};
#define SortSpecial(vec,Struct,Member) \
do { \
std::vector<decltype(Struct::Member)> vt{}; \
std::transform(vec.begin(), vec.end(), std::back_inserter(vt), [](const Struct& s) {return s.Member; }); \
std::sort(vt.begin(), vt.end()); \
std::for_each(vec.begin(), vec.end(), [&vt, i = 0U](Struct & s) mutable {s.Member = vt[i++]; }); \
} while (false)
int main()
{
// Define a vector of struct Test
std::vector<Test> tv{ {1,1,9},{2,2,8},{3,3,7},{4,4,6},{5,5,5} };
for (const Test& t : tv) std::cout << t.a << " " << t.b << " " << t.toSort << "\n";
// Call sort macro
SortSpecial(tv, Test, toSort);
std::cout << "\n\nSorted\n";
for (const Test& t : tv) std::cout << t.a << " " << t.b << " " << t.toSort << "\n";
}
Since macros shouldn't be used in C++, here my questions:
1. Is a solution with the algorithm library possible?
2. Or can this be achieved via templates?
To translate your current solution to a template solution is fairly straight forward.
template <typename T, typename ValueType>
void SpecialSort(std::vector<T>& vec, ValueType T::* mPtr) {
std::vector<ValueType> vt;
std::transform(vec.begin(), vec.end(), std::back_inserter(vt), [&](const T& s) {return s.*mPtr; });
std::sort(vt.begin(), vt.end());
std::for_each(vec.begin(), vec.end(), [&, i = 0U](T& s) mutable {s.*mPtr = vt[i++]; });
}
And we can call it by passing in the vector and a pointer-to-member.
SpecialSort(tv, &Test::toSort);
Somewhow like this (You just need to duplicate, rename and edit the "switchToShort" funtion for the rest of the variables if you want):
#include <iostream>
#include <vector>
struct Test {
int a{};
int b{};
int toSort{};
};
void switchToShort(Test &a, Test &b) {
if (a.toSort > b.toSort) {
int temp = a.toSort;
a.toSort = b.toSort;
b.toSort = temp;
}
}
//void switchToA(Test& a, Test& b) { ... }
//void switchToB(Test& a, Test& b) { ... }
inline void sortMemeberValues(std::vector<Test>& data, void (*funct)(Test&, Test&)) {
for (int i = 0; i < data.size(); i++) {
for (int j = i + 1; j < data.size(); j++) {
(*funct)(data[i], data[j]);
}
}
}
int main() {
std::vector<Test> tv { { 1, 1, 9 }, { 2, 2, 8 }, { 3,3 ,7 }, { 4, 4, 6 }, { 5, 5, 5} };
sortMemeberValues(tv, switchToShort);
//sortMemeberValues(tv, switchToA);
//sortMemeberValues(tv, switchToB);
for (const Test& t : tv) std::cout << t.a << " " << t.b << " " << t.toSort << "\n";
}
With range-v3 (and soon ranges in C++20), you might simply do:
auto r = tv | ranges::view::transform(&Test::toSort);
std::sort(r.begin(), r.end());
Demo

set_interaction example with custom vector not working

I'm looking to get intersection of two custom vectors - v and w - and then deleting common elements from original vector - v. But somehow size of y in my case is 0 always
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class A{
public:
int x;
A(int i) { x = i; }
~A() {}
void getx() { cout << x << " "; }
friend ostream &operator<<(ostream &o, const A&a) {
cout << a.x;
return o;
}
};
struct mycomparer {
bool operator()(const A* a, const A* b) {
return a->x < b->x;
}
};
int main()
{
vector<A*> v;
v.push_back(new A(1));
v.push_back(new A(2));
v.push_back(new A(4));
v.push_back(new A(3));
v.push_back(new A(5));
vector<A*> w;
w.push_back(new A(3));
w.push_back(new A(2));
vector<A*> y;
vector<A*>::iterator it, st;
it = set_intersection(v.begin(), v.end(), w.begin(), w.end(), y.begin(), mycomparer());
cout << " y size " << y.size() << endl;
if (y.size()) {
for (st = y.begin(); st != y.end(); st++)
v.erase(st);
}
for (st = v.begin(); st != v.end(); st++) {
printf("%d ", (*st)->x);
}
cout << endl;
return 0;
}
This is just a sample which I wrote and my intend is not to check for any other C++ rules.
You haven't obeyed the requirements of std::set_intersection.
Constructs a sorted range beginning at d_first consisting of elements that are found in both sorted ranges [first1, last1) and [first2, last2). If some element is found m times in [first1, last1) and n times in [first2, last2), the first std::min(m, n) elements will be copied from the first range to the destination range. The order of equivalent elements is preserved. The resulting range cannot overlap with either of the input ranges.
Neither v nor w are sorted w.r.t mycomparer. That's the first undefined behaviour.
Just passing y.begin() does not mean elements are added to y, for that you need std::back_inserter(y). That's the second undefined behaviour.
You haven't obeyed the requirements of std::vector::erase. It's argument is an iterator into that vector. You are using an iterator from y, not v. That's the third undefined behaviour.
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
class A{
public:
int x;
A(int i) { x = i; }
~A() {}
void getx() { cout << x << " "; }
friend ostream &operator<<(ostream &o, const A&a) {
cout << a.x;
return o;
}
};
struct mycomparer {
bool operator()(const A* a, const A* b) {
return a->x < b->x;
}
};
int main()
{
std::vector<A*> v;
v.push_back(new A(1));
v.push_back(new A(2));
v.push_back(new A(4));
v.push_back(new A(3));
v.push_back(new A(5));
std::sort(v.begin(), v.end(), mycomparer());
std::vector<A*> w;
w.push_back(new A(3));
w.push_back(new A(2));
std::sort(w.begin(), w.end(), mycomparer());
std::vector<A*> y;
set_intersection(v.begin(), v.end(), w.begin(), w.end(), std::back_inserter(y), mycomparer());
std::cout << " y size " << y.size() << std::endl;
for (st = y.begin(); st != y.end(); st++)
v.erase(std::find(v.begin(), v.end(), *st));
for (st = v.begin(); st != v.end(); st++) {
std::cout << (*st)->x) << std::endl;
}
return 0;
}
As an aside, you could instead use std::set_difference to find the elements in v not in w directly.
There are many issues with your code... I just put them in modified code
#include <iostream>
#include <memory>
#include <vector>
#include <algorithm>
// don't using namespace std;
class A {
private:
int x; // don't expose internals
public:
constexpr A(int i) noexcept : x(i) {}
constexpr int GetX() const noexcept { return x; } // don't make a getter to print
friend std::ostream& operator<< (std::ostream& o, const A& a) {
o << a.x; // don't push to cout in an ostream operator <<
return o;
}
};
// use lambda instead of functors
static constexpr auto mycomparer =
[](std::shared_ptr<A> const& a, std::shared_ptr<A> const& b) noexcept {
return a->GetX() < b->GetX();
};
int main()
{
// you were not deleting the new elements: memory leak
std::vector<std::shared_ptr<A>> v; // e.g. use smart pointers
v.push_back(std::make_shared<A>(1));
v.push_back(std::make_shared<A>(2));
v.push_back(std::make_shared<A>(4));
v.push_back(std::make_shared<A>(3));
v.push_back(std::make_shared<A>(5));
std::vector<std::shared_ptr<A>> w;
w.push_back(std::make_shared<A>(3));
w.push_back(std::make_shared<A>(2));
std::vector<std::shared_ptr<A>> y;
//you have to sort before calling set_intersection
std::sort(std::begin(v), std::end(v), mycomparer);
std::sort(std::begin(w), std::end(w), mycomparer);
std::set_intersection(
std::cbegin(v), std::cend(v), // use const iterators
std::cbegin(w), std::cend(w),
std::back_inserter(y), mycomparer); // you cannot iterate over an empty array. Use the backinserter
std::cout << " y size " << y.size() << '\n';
// you cannot use an iterator to a vector y to delete from vector v!
//if (y.size() > 0) { // not required
for (auto const& el : y)
v.erase(std::find(std::cbegin(v), std::cend(v), el));
//}
for (auto const& el : v) {
std::cout << el->GetX() << " ";
}
std::cout << '\n'; // prefer \n over endl for speed
//return 0; // not required
}
1) In vector w you should push new A(2) first, then new A(3). For your actual code, your vectors must be sorted according to the comparator beforehand, as previously mentioned in commentaries, or you absolutely cannot use set_intersection.
2) vector y has size 0, because set_intersection does not insert new elements at iterator, but instead assigns with operator =. Instead of y.begin() you should use std::back_inserter(y), which would actually insert elements on assignment.

How to link elements from different vectors with each other?

I want to write a program which reads names in a vector. After that it should read ages into another vector. (that's done)
The first element of the name-vector should be connected to the first element of the age-vector, so if I use any kind of sort() function on the name-vector the age-vector gets sorted as well.
Is there any way to realize this in an easy way?
class Name_pairs {
public:
//member functions
int read_names();
int read_ages();
int print();
private:
vector<double> age;
vector<string> name;
};
int Name_pairs::read_names() {
cout << "Please enter different names, you want to store in a vector:\n";
for (string names; cin >> names;) {
name.push_back(names);
}
cin.clear();
cout << "You entered following names:\n\t";
for (int i = 0; i < name.size(); i++) {
cout << name[i] << " \n\t";
}
return 0;
}
int Name_pairs::read_ages() {
cout << "\nPlease enter an age for every name in the vector.\n";
for (double ages; cin >> ages;) {
age.push_back(ages);
}
return 0;
}
I think you need a std::vector of a coupled type.
struct Name_pair {
double age;
string name;
};
Than you can use std::vector<Name_pair> and use a lambda
auto comparator = [](const Name_pair& first, const Name_pair& second){return first.age <second.age;};
to sort your vector with std::sort.
Name_pairs = std::vector<Name_pair>;
// fill vector
std::sort(Name_pairs.begin(), Name_pairs.end(), comparator);
Here is a working example.
#include <vector>
#include <algorithm>
#include <string>
#include <iostream>
struct Name_pair {
double age;
std::string name;
};
int main() {
std::vector<Name_pair> Name_pairs{{13, "Hallo"}, {32, "Welt"}, {1, "Georg"}};
auto comparator = [](const Name_pair& first, const Name_pair& second) { return first.age < second.age; };
std::sort(Name_pairs.begin(), Name_pairs.end(), comparator);
for (const auto np : Name_pairs) {
std::cout << np.name << "\n";
}
}
It prints
Georg
Hallo
Welt
If you want to implement a data-oriented design by using separate vectors instead of a single vector of classes, you could use a vector of indeces and sort it.
The following is just an example:
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
class Customers
{
std::vector<double> ages_;
std::vector<std::string> names_;
template <typename Comparator>
auto make_indeces(Comparator &&comp)
{
std::vector<size_t> indeces(names_.size());
std::iota(indeces.begin(), indeces.end(), 0);
std::sort(indeces.begin(), indeces.end(), comp);
return indeces;
}
template <typename Type>
void reorder_vector(std::vector<Type> &src, std::vector<size_t> const &indeces)
{
std::vector<Type> tmp;
tmp.reserve(src.size());
std::generate_n(
std::back_inserter(tmp), src.size(),
[&src, idx = indeces.cbegin()] () mutable {
return src[*(idx++)];
});
src = std::move(tmp);
}
public:
void add(std::string const &name, double age)
{
names_.push_back(name);
ages_.push_back(age);
}
void sort_by_names()
{
auto indeces = make_indeces([this] (size_t i, size_t j) {
return names_[i] < names_[j];
});
reorder_vector(names_, indeces);
reorder_vector(ages_, indeces);
}
void show_sorted_by_ages()
{
auto indeces = make_indeces([this] (size_t i, size_t j) {
return ages_[i] < ages_[j];
});
for (auto i : indeces)
std::cout << names_[i] << ' ' << ages_[i] << '\n';
}
void show()
{
for (size_t i = 0; i < names_.size(); ++i)
std::cout << names_[i] << ' ' << ages_[i] << '\n';
}
};
int main(void)
{
Customers c;
c.add("Adam", 23);
c.add("Eve", 21);
c.add("Snake", 66.6);
c.add("Apple", 3.14);
std::cout << "Sorted by ages (doesn't modify the internal order):\n";
c.show_sorted_by_ages();
std::cout << "\nInternal order:\n";
c.show();
c.sort_by_names();
std::cout << "\nInternal order after sorting by names:\n";
c.show();
}
Testable HERE.

C++ iterators in lists

I have a question about iterators on lists. In function I have to compare the doubles, but I don't know how to get the elements from the second level, with only iterators to the first level.
void function (std::list<std::list <double>>::iterator *begin, std::list<std::list <double>>::iterator *end)
{
//do something
}
int main()
{
std::list <std::list <double>> a_list;
function (a_list.begin(), a_list.end());
}
void function (list<list <double> >::iterator begin, list<list <double> >::iterator end)
{
for(std::list<std::list <double> >::iterator it =begin;it!= end;it++)
{
for(std::list <double>:: iterator it_inner = (*it).begin(); it_inner != (*it).end();it_inner++)
{
printf("%f ",*it_inner );
}
printf("\n");
}
}
int main()
{
std::list <std::list <double> > a_list;
for(int i=0;i<=3;i++)
{
std::list <double> inner_list;
for(double j=0;j<=8;j+=2.2)
{
inner_list.push_back(j);
}
a_list.push_back(inner_list);
}
function (a_list.begin(), a_list.end());
}
You can pass the iterators as parameters or just the entire list, like this:
#include <iostream>
#include <list>
using namespace std;
void funcA (list<list<double>>::iterator begin, list<list<double>>::iterator end) {
//do something
list<double>::iterator sublist1 = begin->begin();
cout << *sublist1 + 1 << endl;
}
void funcB (list<list<double>> list) {
for (auto&& sublist: list) {
for (auto&& value: sublist) {
cout << value << ' ';
}
}
cout << endl;
}
int main() {
list <list<double>> a_list = {{1,2,3},{4,5,6}};
// list<list<double>>::iterator a = a_list.begin();
// list<double>::iterator b = a->begin();
//
// cout << *b + 2 << endl;
funcA(a_list.begin() , a_list.end());
funcB(a_list);
}

iterating over vector of vectors in c++

I've just started to code in C++, so i'm new to STL .
Here i'm trying to iterate over a graph stored as vector of vectors.
#include <iostream>
#include <vector>
#include <iostream>
using namespace std;
int reach(vector<vector<int> > &adj, int x, int y) {
vector<vector<int> >::iterator it;
vector<int>::iterator i;
for (it = adj.begin(); it != adj.end(); it++)
{
cout << (*it) << endl;
if ((*it) == x)
for (i = (*it).begin(); i != (*it).end(); i++)
{
cout << (*i) << endl;
if ((*i) == y)
return 1;
}
}
return 0;
}
int main()
{
}
I'm getting an error std::vector<int> is not derived from const gnu cxx. Can someone point me in the right direction ?
*it pointing to vector not int that is why you are getting error
following code may work for you
#include <vector>
#include <iostream>
using namespace std;
int reach(vector<vector<int> > &adj, int x, int y) {
vector<vector<int> >::iterator it;
vector<int>::iterator i;
for (it = adj.begin(); it != adj.end(); it++)
{
cout << (*(*it).begin()) << endl;
if (( (*(*it).begin())) == x)
for (i = (*it).begin(); i != (*it).end(); i++)
{
cout << (*i) << endl;
if ((*i) == y)
return 1;
}
}
return 0;
}
int main()
{
}
for accessing first element of the vector of the use
(*(*it).begin()) in place of (*it)
if you are studying graph then use array of vector. for more details please go through following url
C++ Depth First Search (DFS) Implementation
cout << (*it) << endl;
Here, you declared it as a:
vector<vector<int> >::iterator it;
Therefore, *it is a:
vector<int>
So you are attempting to use operator<< to send it to std::cout. This, obviously, will not work. This is equivalent to:
vector<int> v;
cout << v;
There is no operator<< overload that's defined for what cout is, and a vector<int>. As you know, in order to print the contents of a vector, you have to iterate over its individual values, and print its individual values.
So, whatever your intentions were, when you wrote:
cout << (*it) << endl;
you will need to do something else, keeping in mind that *it here is an entire vector<int>. Perhaps your intent is to iterate over the vector and print each int in the vector, but you're already doing it later.
Similarly:
if ((*it) == x)
This won't work either. As explained, *it is a vector<int>, which cannot be compared to a plain int.
It is not clear what your intentions are here. "Graph stored as a vector or vectors" is too vague.
The following code compiles with the option std=c++11. But x is missing in vector<vector<int>>. If adj had type vector<pair<int, vector<int>>> it would better match.
The following code compiles for vector<vector<int>> but it doesn't use x.
using std::vector;
using std::pair;
using std::cout;
using std::endl;
int reach(vector<vector<int> > &adj, int x, int y) {
vector<vector<int> >::iterator it;
vector<int>::iterator i;
for(it=adj.begin();it!=adj.end();it++)
{
// cout << (*it) << endl;
for (const auto& nexts: *it)
cout << nexts << ' ';
cout << endl;
for(i=(*it).begin();i!=(*it).end();i++)
{
cout << (*i) << endl;
if((*i)==y)
return 1;
}
}
return 0;
}
This code compiles with <vector<pair<int, vector<int>>> and uses x.
using std::vector;
using std::pair;
using std::cout;
using std::endl;
int reach(vector<pair<int, vector<int> > > &adj, int x, int y) {
vector<pair<int, vector<int> > >::iterator it;
vector<int>::iterator i;
for(it=adj.begin();it!=adj.end();it++)
{
cout << it->first << endl;
if (it->first == x)
for(i=it->second.begin();i!=it->second.end();i++)
{
cout << (*i) << endl;
if((*i)==y)
return 1;
}
}
return 0;
}
Wrap it up in an iterator.
This can be templated for reuse.
Here is a minimal working example for the std::vector<T> container:
#include <iostream>
#include <utility>
#include <vector>
/// Iterable vector of vectors
/// (This just provides `begin` and `end for `Vector2Iterable<T>::Iterator`).
template<typename T>
class VovIterable
{
public:
static const std::vector<T> EMPTY_VECTOR;
/// Actual iterator
class Iterator
{
typename std::vector<std::vector<T>>::const_iterator _a1;
typename std::vector<T>::const_iterator _a2;
typename std::vector<std::vector<T>>::const_iterator _end;
public:
/// \param a1 Outer iterator
/// \param a2 Inner iterator
/// \param end End of outer iterator
explicit Iterator(typename std::vector<std::vector<T>>::const_iterator a1, typename std::vector<T>::const_iterator a2, typename std::vector<std::vector<T>>::const_iterator end)
: _a1(a1)
, _a2(a2)
, _end(end)
{
Check();
}
bool operator!=(const Iterator &b) const
{
return _a1 != b._a1 || _a2 != b._a2;
}
Iterator &operator++()
{
++_a2; // Increment secondary
Check();
return *this;
}
const T &operator*() const
{
return *_a2;
}
private:
void Check()
{
while (true)
{
if (_a2 != _a1->end()) // Is secondary live?
{
break;
}
// Increment primary
_a1++;
if (_a1 == _end) // Is primary dead?
{
_a2 = EMPTY_VECTOR.end();
break;
}
_a2 = _a1->begin(); // Reset secondary
}
}
};
private:
std::vector<std::vector<T>> _source;
public:
explicit VovIterable(std::vector<std::vector<T>> source)
: _source(std::move(source))
{
}
/// Start of vector of vectors
[[nodiscard]] Iterator begin() const
{
if (this->_source.empty())
{
return end();
}
return Iterator(this->_source.cbegin(), this->_source.cbegin()->cbegin(), this->_source.cend());
}
/// End of vector of vectors
[[nodiscard]] Iterator end() const
{
return Iterator(this->_source.cend(), EMPTY_VECTOR.end(), this->_source.cend());
}
};
template<typename T>
const std::vector<T> VovIterable<T>::EMPTY_VECTOR = {0};
/// Sample usage
int main()
{
std::vector<std::vector<int>> myVov{{1, 2, 3},
{4, 5, 6},
{7, 8, 9}};
for (int i: VovIterable(myVov))
{
std::cout << i << std::endl;
}
return 0;
}