#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
#include<iomanip>
using namespace std;
typedef pair<int, int> intPair;// rename intPair
typedef vector<double> doubleVector; //rename doubleVetcor
typedef vector<intPair> intPairVector; // rename intPairVector
// Union-Find Disjoint Sets Library written in OOP manner, using both path compression and union by rank heuristics
class UnionFind { // OOP style
private:
doubleVector p, rank, setSize; // remember: vi is vector<double>
int numSets;
public:
UnionFind(int N) {
setSize.assign(N, 1);
numSets = N;
rank.assign(N, 0);
p.assign(N, 0);
for (int i = 0; i < N; i++)
p[i] = i;
}
int findSet(int i) {
return (p[i] == i) ? i : (p[i] = findSet(p[i]));
}
bool isSameSet(int i, int j) {
return findSet(i) == findSet(j);
}
void unionSet(int i, int j) {
if (!isSameSet(i, j)) {
numSets--;
int x = findSet(i), y = findSet(j);
// rank is used to keep the tree short
if (rank[x] > rank[y]) {
p[y] = x;
setSize[x] += setSize[y];
}
else{
p[x] = y;
setSize[y] += setSize[x];
if (rank[x] == rank[y])
rank[y]++;
}
}
}
int numDisjointSets() {
return numSets;
}
int sizeOfSet(int i) {
return setSize[findSet(i)];
}
};
vector<intPairVector> AdjList;
int main() {
int num_verts=0;
cin >> num_verts;
//Pre-allocate a vector of num_verts rows, each of which is a vector
//of num_verts copies of 0.0
vector<vector<double>> matrix(num_verts, vector<double>(num_verts,0.0));
//Requires c++11 or higher
for(int row = 0; row<num_verts;++row) {
for(int col = 0; col<num_verts; ++col){
cin >> matrix[row][col];
}
}
//print out the matrix we just read
for(int row = 0; row<num_verts; ++row) {
for(int col=0; col<num_verts;++col){
cout << setprecision(2) << fixed << matrix[row][col] << "\t";
}
cout << "\n";
}
// Kruskal's algorithm merged
AdjList.assign(num_verts, intPairVector());
vector< pair<double, intPair> > EdgeList; // (weight, two vertices) of the edge
for (int row = 0; row<num_verts; ++row) {
for(int col=0; col<num_verts;++col){
EdgeList.push_back(make_pair(matrix[row][col], intPair(row,col)));
AdjList[row].push_back(intPair(row,matrix[row][col]));
AdjList[col].push_back(intPair(col,matrix[row][col]));
}
}
sort(EdgeList.begin(), EdgeList.end()); // sort by edge weight O(E log E)
// note: pair object has built-in comparison function
double mst_cost = 0.0;
UnionFind UF(num_verts); // all V are disjoint sets initially
for (int i = 0; i < num_verts*num_verts; i++) { // for each edge, O(E)
pair<double,intPair> front = EdgeList[i];
if (!UF.isSameSet(front.second.first, front.second.second)) { // check
mst_cost += front.first; // add the weight of e to MST
UF.unionSet(front.second.first, front.second.second); // link them
}
} // note: the runtime cost of UFDS is very light
//display the weight of the MST
cout << setprecision(2) << fixed << mst_cost << endl;
return 0;
}
I am trying to display the minimum spanning tree from this code, I cannot figure out how to get this code to display the modified matrix. The code is working correctly, by that I mean it is compiling and calculating the correct weight for the graph. However, I am unsure how to display the minimum spanning tree from using Kruskals algorithm. Thanks for any help
Whenever you add the weight of an edge to the weight of the MST, you should also add that edge to a list to keep track of the MST edges.
Related
I'm trying to port a few functions over to r from cpp using rcpp directly using sourceCpp. I'm a total novice so apologies for poorly used language or post. Trying to port over the Bellman Ford algorithm (from Gupte, Shankar, Li, Muthukrishnan, Iftode).
I'm getting two errors:
cannot convert 'SEXP' to 'Rcpp::traits::input_parameter::type* {aka Rcpp::InputParameter*} in initialization
invalid user-defined conversion from 'Rcpp::traits::input_parameter::type {aka Rcpp::InputParameter}' to 'int' [-fpermissive]
Bonus confusion: Also, R studio shows line errors as outside of the range of the code (error in line 600, but Cpp code is only 500 lines long)
I'm guessing this is something to do with class types, wrapping functions, not being able to use pointers or something like that in the very first line. Please let me know how I might adjust this code to correctly export this function to r.
Thank you.
#include <Rcpp.h> // added this
using namespace Rcpp; // added
#define MAXV 100000
using namespace std; // commented this out...? don't, throws a lot of errors
struct edge {
int u, v, weight;
edge(int _u, int _v) {
u = _u, v = _v, weight = -1;
}
edge(int _u, int _v, int _weight) {
u = _u, v = _v, weight = _weight;
}
};
// general stuff
int LPvalue; // value for the dual LP
int cycleCount;
int V, E;
vector <edge> edges;
vector <edge> original_edges;
ofstream results, summary;
// stuff for labeling
vector <int> edgesDAG; // edges left over from eulerian subgraph
vector <int> edgesEulerian; // maximal eulerian subgraph
set<int> adjDAG[MAXV]; // these adjacency lists still just keep edge indices
set<int> adjEulerian[MAXV];
bool inEulerian[MAXV];
// stuff for Bellman-Ford
int dist[MAXV]; // vertex -> distance
// [[Rcpp::export]] //ERRORS
void bellman_ford(int *pred) {
for(int i = 0; i < V; i++) {
dist[i] = V;
pred[i] = -1;
}
dist[0] = 0;
int i;
for(i = 0; i < V; i++) {
bool changed = false;
//printf("%d",i);
for(int j = 0; j < E; j++) {
int u = edges[j].u;
int v = edges[j].v;
int w = edges[j].weight;
if(dist[v] > dist[u] + w) {
dist[v] = dist[u] + w;
pred[v] = j;
changed = true;
}
}
if(dist[0] < 0) {
break;
}
if(!changed) {
printf("Bellman Ford done after %d of %d iters\n", i, V);
//results << "Bellman-Ford done after " << i << " of " << V << " iters" << endl;
break;
}
}
printf("Bellman Ford took %d of %d iters\n", i+1, V);
}
use std::vector<int> instead of int *
use Rcpp::Rcout instead of std::ofstream
The following code should compile:
#include <Rcpp.h> // added this
using namespace Rcpp; // added
#define MAXV 100000
using namespace std; // commented this out...? don't, throws a lot of errors
struct edge {
int u, v, weight;
edge(int _u, int _v) {
u = _u, v = _v, weight = -1;
}
edge(int _u, int _v, int _weight) {
u = _u, v = _v, weight = _weight;
}
};
// general stuff
int LPvalue; // value for the dual LP
int cycleCount;
int V, E;
vector <edge> edges;
vector <edge> original_edges;
// stuff for labeling
vector <int> edgesDAG; // edges left over from eulerian subgraph
vector <int> edgesEulerian; // maximal eulerian subgraph
set<int> adjDAG[MAXV]; // these adjacency lists still just keep edge indices
set<int> adjEulerian[MAXV];
bool inEulerian[MAXV];
// stuff for Bellman-Ford
int dist[MAXV]; // vertex -> distance
// [[Rcpp::export]]
void bellman_ford(std::vector<int> pred) {
for(int i = 0; i < V; i++) {
dist[i] = V;
pred[i] = -1;
}
dist[0] = 0;
int i;
for(i = 0; i < V; i++) {
bool changed = false;
//printf("%d",i);
for(int j = 0; j < E; j++) {
int u = edges[j].u;
int v = edges[j].v;
int w = edges[j].weight;
if(dist[v] > dist[u] + w) {
dist[v] = dist[u] + w;
pred[v] = j;
changed = true;
}
}
if(dist[0] < 0) {
break;
}
if(!changed) {
Rcpp::Rcout << "Bellman-Ford done after " << i << " of " << V << " iters" << endl;
break;
}
}
Rcpp::Rcout << "Bellman Ford took" << i + 1 << " of " << V << " iters" << std::endl;
}
Using codeblocks, I have written a code that displays an adjacency matrix, BFS and DFS search order, and whether or not graph is bipartite.
The graph is passed as a program argument through main as a .txt file.
I have two identical .txt files with different names and drastically different outputs. I have absolutely no idea why.
for graph0.txt
I have this output
For graphNull.txt
I have this output
With the exception of the file name, the files are identical. I even typed them the exact same way just to make sure. Why is this happening?
#include <iostream>
using namespace std;
#include "Graph.h"
int main(int argc, char *argv[])
{
Graph g;
g.load(argv[1]);
cout << endl << "Adjacency Matrix" << endl;
g.display();
g.displayDFS(0);
g.displayBFS(0);
cout << "Bipartite: ";
if (g.isBipartite())
cout << "TRUE";
else
cout << "FALSE";
cout << endl;
return 0;
}
Graph.h
#ifndef GRAPH_H
#define GRAPH_H
#include "QueueInt.h"
#include "StackInt.h"
class Graph {
public:
Graph(); // constructor
~Graph(); // destructor
// Load the graph from a file
void load(char *filename);
// Display the adjacency matrix
void display() const;
// Display the depth first search from the given vertex
void displayDFS(int vertex) const;
// Display the breadth first search from the given vertex
void displayBFS(int vertex) const;
// Determine whether the graph is bipartite or not
bool isBipartite() const;
private:
string fName;
int numVert;
int** mat;
int* visited;
int* dfs;
void helperDFS(int vertex, int &counter, int* visited, int* dfs) const;
};
#endif
Graph.cpp
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
#include "Graph.h"
#include "QueueInt.h"
#include "StackInt.h"
// Constructor
Graph::Graph()
{
fName = "";
numVert = 0;
}
// Destructor
Graph::~Graph()
{
delete mat;
delete visited;
delete dfs;
}
// Load the graph from a file
void Graph::load(char* filename)
{
int numStore;
fName = filename;
fstream fin;
fin.open(filename);
fin >> numStore;
numVert = numStore;
mat = new int *[numVert];
int a;
int b;
for (int i = 0; i < numVert ; i++){
//matrix is created
mat[i] = new int[numVert];
for (int j = 0; j < numVert; j++){
mat[i][j] = 0;
}
}
while (fin >> a >> b){
mat[a][b] = 1;
mat[b][a] = 1;
}
}
// Display the adjacency matrix
void Graph::display() const
{
for (int i = 0; i < numVert; i++){
for (int j = 0; j < numVert; j++){
cout << mat[i][j] << " ";
}
cout << "\n";
}
}
// Displays the depth first search starting at the given vertex
void Graph::helperDFS(int vertex, int &counter, int* visited, int* dfs) const {
visited[vertex] = 1;
dfs[counter] = vertex;
counter++;
for (int j = 0; j < numVert; j++){
if (mat[vertex][j] == 1 && visited[j] != 1){
helperDFS(j, counter, visited, dfs);
}
}
}
void Graph::displayDFS(int vertex) const
{
int counter = 0;
int* visited = new int [numVert];
for(int i = 0; i < numVert; i++){
visited[i] = 0;
}
int* dfs = new int [numVert];
helperDFS(vertex, counter, visited, dfs);
cout << "DFS at vertex " << vertex << ": ";
for (int i = 0; i < numVert; i++){
cout << dfs[i] << " ";
}
}
// Perform breadth first search starting at the given vertex
void Graph::displayBFS(int vertex) const
{
int v = vertex;
int vert;
int bfs[numVert];
int counter = 0;
int* visited = new int [numVert];
QueueInt q; //empty q
//create visited array initizalized to false for each vertex
for (int i = 0; i < numVert; i++){
visited[i] = 0;
}
cout << endl;
//mark v as visited
visited[vertex] = 1;
//add v to queue
q.enqueue(vertex);
//process v to array for output
bfs[counter] = vertex;
counter ++;
while(!q.isEmpty()){
vert = q.dequeue();
for (int j = 0; j < numVert; j++){
if (mat[vert][j] == 1 && visited[j]!=1){
visited[j] = 1;
q.enqueue(j);
bfs[counter] = j;
counter ++;
}
}
}
cout << "BFS at vertex " << v << ": ";
for (int i = 0; i < numVert; i++){
cout << bfs[i] << " ";
}
cout << "\n";
}
// Determine whether the graph is bipartite or not
bool Graph::isBipartite() const
{
bool flag = true;
int color[numVert];
//ASSIGN COLOR ELEMENTS TO 0
for (int i = 0; i < numVert; i++){
color[i] = 0;
}
//ASSIGN CURRENT ELEMENT COLOR 1
for (int i =0; i < numVert; i++){
if (color[i] == 0){
color[i] = 1;
}
//ASSIGN ADJACENT ELEMENTS COLOR 2
for (int j = 0; j < numVert; j++){
if (mat[i][j] == 1){
color[j] = 2;
}
}
//FOR ELEMENTS WITH COLOR TWO, CHECK FOR ADJACENCY
for (int j = 0; j < numVert; j++){
if (color[j] == 2){
for (int k = 0; k < numVert; k++){ //will have a self check, but thats not a problem given no self loops
if (color[k] == 2){
if (mat[j][k] == 1){
flag = false;
return flag;
}
}
}
}
}
//RESET COLORS, RUN AGAIN
for (int h = 0; h < numVert; h++){
color[h] = 0;
}
}
return flag;
}
QueueInt.h
#ifndef QUEUEINT_H
#define QUEUEINT_H
#include <queue>
using namespace std;
class QueueInt
{
public:
// Add an integer to the back of the queue.
void enqueue(int val);
// Removes and returns an integer from the front of the queue. Aborts the
// program is the queue is empty.
int dequeue();
// Returns but does not remove the integer at the front of the queue. Aborts the
// program is the queue is empty.
int front() const;
// Returns true if the queue is empty.
bool isEmpty() const;
private:
queue<int> queueObj; // underyling STL queue object
};
#endif // QUEUE_H
QueueInt.cpp
#include <iostream>
#include <cstdlib>
using namespace std;
#include "QueueInt.h"
// Add an integer to the back of the queue.
void QueueInt::enqueue(int val)
{
queueObj.push(val);
}
// Removes and returns an integer from the front of the queue. Aborts the
// program is the queue is empty.
int QueueInt::dequeue()
{
int val = front();
queueObj.pop();
return val;
}
// Returns but does not remove the integer at the front of the queue. Aborts the
// program is the queue is empty.
int QueueInt::front() const
{
if (isEmpty()) {
cerr << "Tried to access empty queue --> aborting program" << endl;
exit(-1);
}
return queueObj.front();
}
// Returns true if the queue is empty.
bool QueueInt::isEmpty() const
{
return queueObj.empty();
}
I have the following piece of code:
bool *pho=new bool[n];
memset(pho, 0, sizeof(bool) * n);
for (int i = 0; i < m; i++) {
int d=2;
cout << "i=" << i << ", d="<<d<< endl;
pho[d] = true;
}
Running with input n=8 results in the following output:
i=0, d=2
i=1, d=2
[Segfault]
I don't understand why this is happening! Setting the same location in the array results in a segfault for some reason. I have run the program several times and it always produces the same output.
Stepping through the code with a debugger, I can see that the value of d (the index) is 2 when the array gets accessed.
I have tried using global arrays and also static global arrays, both of which result in the same error.
Is there something wrong with my IDE and compiler? I am using MinGW with Eclipse CDT, running with std/c++11 option enabled.
Here is the whole source file, in case any other part of the program is causing problems:
#include <iostream>
#include <queue>
#include <vector>
#include <unordered_set>
#include <utility>
#include <algorithm>
#include <cstring>
using namespace std;
vector<unordered_set<int>> adj;
static bool *visited;
pair<int, int> dfs(int node) {
if (visited[node])
return make_pair(0, node);
pair<int, int> best = make_pair(0, node);
for (int neigh : adj[node]) {
pair<int, int> alt = dfs(node);
alt.second++;
best = max(best, alt);
}
return best;
}
int main(int argc, char** argv) {
int n, m, def;
cin >> n ;
cin >> m;
bool *pho=new bool[n];
memset(pho, 0, sizeof(bool) * n);
int *degrees=new int[n];
memset(degrees, 0, sizeof(int) * n);
cout << "n="<<n<<", m="<<m<<endl;
for (int i = 0; i < m; i++) {
int d=2;
cout << "i=" << i << ", d="<<d<< endl;
pho[d] = true;
}
for (int i = 0; i < n - 1; i++) {
int a, b;
cin >> a >> b;
adj[a].insert(b);
adj[b].insert(a);
degrees[a]++;
degrees[b]++;
}
queue<int> next;
for (int i = 0; i < n; i++) {
if (degrees[i] == 0) {
next.push(i);
}
}
while (!next.empty()) {
int node = next.front();
next.pop();
if (pho[node])
continue;
for (int neigh : adj[node]) {
adj[node].erase(neigh);
adj[neigh].erase(node);
degrees[node]--;
degrees[neigh]--;
if (degrees[neigh] == 1)
next.push(neigh);
}
}
visited=new bool[n];
memset(visited, 0, sizeof(bool) * n);
pair<int, int> pivot = dfs(def);
memset(visited, 0, sizeof(bool) * n);
pair<int, int> end = dfs(pivot.second);
int dist = end.first; //number of edges she only has to walk once
int tree = n - 1; //number of edges in tree
int otherdist = tree - dist; //number of edges she has to walk twice
int total = dist + otherdist * 2;
cout << total << endl;
return 0;
}
These lines are wrong :
adj[a].insert(b);
adj[b].insert(a);
You need to create unordered_map instance with a and b as keys, then respectively insert b and a as value. You don't need to have a vector of sets if you need key-value pairs.
So I am having trouble with my code and cant figure out exactly what the problem is. I am supposed to take in a text file, where the first line shows the number of vertices, and the second line shows the number of edges.From this text file I am trying to take in the values shown then build a graph and determine whether or not it contains a cycle. Then display nodes which have no incoming edges.
t1.txt
3
2
1,2,
2,3
I am not sure exactly where I am going wrong here.
t2.txt
5
5
3,4,
4,5,
2,3,
1,3,
3,5
//
#include <iostream>
#include <fstream>
#include <sstream>
#include<string>
#include<list>
#include <limits.h>
#include <stack>
#include<stdlib.h>
#include <cstdlib>
using namespace std;
class Graph
{
int V; // No. of vertices
list<int> *adj; // Pointer to an array containing adjacency lists
bool isCyclicUtil(int v, bool visited[], bool *rs); // used by isCyclic()
public:
Graph(int V); // Constructor
void addEdge(int v, int w); // to add an edge to graph
bool isCyclic(); // returns true if there is a cycle in this graph
};
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w); // Add w to v’s list.
}
bool Graph::isCyclicUtil(int v, bool visited[], bool *recStack)
{
if(visited[v] == false)
{
// Mark the current node as visited and part of recursion stack
visited[v] = true;
recStack[v] = true;
// Recur for all the vertices adjacent to this vertex
list<int>::iterator i;
for(i = adj[v].begin(); i != adj[v].end(); ++i)
{
if ( !visited[*i] && isCyclicUtil(*i, visited, recStack) )
return true;
else if (recStack[*i])
return true;
}
}
recStack[v] = false; // remove the vertex from recursion stack
return false;
}
// Returns true if the graph contains a cycle, else false.
bool Graph::isCyclic()
{
// Mark all the vertices as not visited and not part of recursion
// stack
bool *visited = new bool[V];
bool *recStack = new bool[V];
for(int i = 0; i < V; i++)
{
visited[i] = false;
recStack[i] = false;
}
// Call the recursive helper function to detect cycle in different
// DFS trees
for(int i = 0; i < V; i++)
if (isCyclicUtil(i, visited, recStack))
return true;
return false;
}
int main()
{
float n ,n2;
string filename,line;
cout << "Enter filename: ";
cin >> filename;
fstream file;
file.open(filename.c_str());
file >> n;
file >> n2;
int num = n;
cout << num << " ";
int num2 = n2;
cout << num2 << " ";
string matrix[num2][2];
//int ** mat = new int*[num2];
int mat[num2][2];
Graph g(num);
while(!file.eof())
{
for(int i = 0; i < num2; i++)
{
//mat[i] = new int[num];
for(int j = 0; j < 2; j++)
{
if(getline(file,line,','))
{
matrix[i][j] = line; // read file into string matrix
istringstream(line) >> mat[i][j]; //convert to int and store in dynamic 2d array
}
}
}
}
cout << endl << "TEST " << mat[0][0] << " " << mat[0][1] << " " << mat[1][0]<< " " << mat[1][1];
for(int i = 0; i <num2-1; i++)
{
int temp1,temp2;
temp1 = mat[i][0];
temp2 = mat[i][1];
g.addEdge(temp1,temp2);
}
if(g.isCyclic())//Here is where the program crashes for input t2.txt
cout << "Graph is not DAG";
else
cout << "Graph is DAG";
return 0;
}
I am trying to take in an input for the dimensions of a 2D matrix. And then use user input to fill in this matrix. The way I tried doing this is via vectors (vectors of vectors). But I have encountered some errors whenever I try to read in data and append it to the matrix.
//cin>>CC; cin>>RR; already done
vector<vector<int> > matrix;
for(int i = 0; i<RR; i++)
{
for(int j = 0; j<CC; j++)
{
cout<<"Enter the number for Matrix 1";
cin>>matrix[i][j];
}
}
Whenever I try to do this, it gives me a subscript out of range error. Any advice?
You have to initialize the vector of vectors to the appropriate size before accessing any elements. You can do it like this:
// assumes using std::vector for brevity
vector<vector<int>> matrix(RR, vector<int>(CC));
This creates a vector of RR size CC vectors, filled with 0.
As it is, both dimensions of your vector are 0.
Instead, initialize the vector as this:
vector<vector<int> > matrix(RR);
for ( int i = 0 ; i < RR ; i++ )
matrix[i].resize(CC);
This will give you a matrix of dimensions RR * CC with all elements set to 0.
I'm not familiar with c++, but a quick look at the documentation suggests that this should work:
//cin>>CC; cin>>RR; already done
vector<vector<int> > matrix;
for(int i = 0; i<RR; i++)
{
vector<int> myvector;
for(int j = 0; j<CC; j++)
{
int tempVal = 0;
cout<<"Enter the number for Matrix 1";
cin>>tempVal;
myvector.push_back(tempVal);
}
matrix.push_back(myvector);
}
Assume we have the following class:
#include <vector>
class Matrix {
private:
std::vector<std::vector<int>> data;
};
First of all I would like suggest you to implement a default constructor:
#include <vector>
class Matrix {
public:
Matrix(): data({}) {}
private:
std::vector<std::vector<int>> data;
};
At this time we can create Matrix instance as follows:
Matrix one;
The next strategic step is to implement a Reset method, which takes two integer parameters that specify the new number of rows and columns of the matrix, respectively:
#include <vector>
class Matrix {
public:
Matrix(): data({}) {}
Matrix(const int &rows, const int &cols) {
Reset(rows, cols);
}
void Reset(const int &rows, const int &cols) {
if (rows == 0 || cols == 0) {
data.assign(0, std::vector<int>(0));
} else {
data.assign(rows, std::vector<int>(cols));
}
}
private:
std::vector<std::vector<int>> data;
};
At this time the Reset method changes the dimensions of the 2D-matrix to the given ones and resets all its elements. Let me show you a bit later why we may need this.
Well, we can create and initialize our matrix:
Matrix two(3, 5);
Lets add info methods for our matrix:
#include <vector>
class Matrix {
public:
Matrix(): data({}) {}
Matrix(const int &rows, const int &cols) {
Reset(rows, cols);
}
void Reset(const int &rows, const int &cols) {
data.resize(rows);
for (int i = 0; i < rows; ++i) {
data.at(i).resize(cols);
}
}
int GetNumRows() const {
return data.size();
}
int GetNumColumns() const {
if (GetNumRows() > 0) {
return data[0].size();
}
return 0;
}
private:
std::vector<std::vector<int>> data;
};
At this time we can get some trivial matrix debug info:
#include <iostream>
void MatrixInfo(const Matrix& m) {
std::cout << "{ \"rows\": " << m.GetNumRows()
<< ", \"cols\": " << m.GetNumColumns() << " }" << std::endl;
}
int main() {
Matrix three(3, 4);
MatrixInfo(three);
}
The second class method we need at this time is At. A sort of getter for our private data:
#include <vector>
class Matrix {
public:
Matrix(): data({}) {}
Matrix(const int &rows, const int &cols) {
Reset(rows, cols);
}
void Reset(const int &rows, const int &cols) {
data.resize(rows);
for (int i = 0; i < rows; ++i) {
data.at(i).resize(cols);
}
}
int At(const int &row, const int &col) const {
return data.at(row).at(col);
}
int& At(const int &row, const int &col) {
return data.at(row).at(col);
}
int GetNumRows() const {
return data.size();
}
int GetNumColumns() const {
if (GetNumRows() > 0) {
return data[0].size();
}
return 0;
}
private:
std::vector<std::vector<int>> data;
};
The constant At method takes the row number and column number and returns the value in the corresponding matrix cell:
#include <iostream>
int main() {
Matrix three(3, 4);
std::cout << three.At(1, 2); // 0 at this time
}
The second, non-constant At method with the same parameters returns a reference to the value in the corresponding matrix cell:
#include <iostream>
int main() {
Matrix three(3, 4);
three.At(1, 2) = 8;
std::cout << three.At(1, 2); // 8
}
Finally lets implement >> operator:
#include <iostream>
std::istream& operator>>(std::istream& stream, Matrix &matrix) {
int row = 0, col = 0;
stream >> row >> col;
matrix.Reset(row, col);
for (int r = 0; r < row; ++r) {
for (int c = 0; c < col; ++c) {
stream >> matrix.At(r, c);
}
}
return stream;
}
And test it:
#include <iostream>
int main() {
Matrix four; // An empty matrix
MatrixInfo(four);
// Example output:
//
// { "rows": 0, "cols": 0 }
std::cin >> four;
// Example input
//
// 2 3
// 4 -1 10
// 8 7 13
MatrixInfo(four);
// Example output:
//
// { "rows": 2, "cols": 3 }
}
Feel free to add out of range check. I hope this example helps you :)
try this. m = row, n = col
vector<vector<int>> matrix(m, vector<int>(n));
for(i = 0;i < m; i++)
{
for(j = 0; j < n; j++)
{
cin >> matrix[i][j];
}
cout << endl;
}
cout << "::matrix::" << endl;
for(i = 0; i < m; i++)
{
for(j = 0; j < n; j++)
{
cout << matrix[i][j] << " ";
}
cout << endl;
}
Vector needs to be initialized before using it as cin>>v[i][j]. Even if it was 1D vector, it still needs an initialization, see this link
After initialization there will be no errors, see this link
What you have initialized is a vector of vectors, so you definitely have to include a vector to be inserted("Pushed" in the terminology of vectors) in the original vector you have named matrix in your example.
One more thing, you cannot directly insert values in the vector using the operator "cin". Use a variable which takes input and then insert the same in the vector.
Please try this out :
int num;
for(int i=0; i<RR; i++){
vector<int>inter_mat; //Intermediate matrix to help insert(push) contents of whole row at a time
for(int j=0; j<CC; j++){
cin>>num; //Extra variable in helping push our number to vector
vin.push_back(num); //Inserting numbers in a row, one by one
}
v.push_back(vin); //Inserting the whole row at once to original 2D matrix
}
I did this class for that purpose. it produces a variable size matrix ( expandable) when more items are added
'''
#pragma once
#include<vector>
#include<iostream>
#include<iomanip>
using namespace std;
template <class T>class Matrix
{
public:
Matrix() = default;
bool AddItem(unsigned r, unsigned c, T value)
{
if (r >= Rows_count)
{
Rows.resize(r + 1);
Rows_count = r + 1;
}
else
{
Rows.resize(Rows_count);
}
if (c >= Columns_Count )
{
for (std::vector<T>& row : Rows)
{
row.resize(c + 1);
}
Columns_Count = c + 1;
}
else
{
for (std::vector<T>& row : Rows)
{
row.resize(Columns_Count);
}
}
if (r < Rows.size())
if (c < static_cast<std::vector<T>>(Rows.at(r)).size())
{
(Rows.at(r)).at(c) = value;
}
else
{
cout << Rows.at(r).size() << " greater than " << c << endl;
}
else
cout << "ERROR" << endl;
return true;
}
void Show()
{
std::cout << "*****************"<<std::endl;
for (std::vector<T> r : Rows)
{
for (auto& c : r)
std::cout << " " <<setw(5)<< c;
std::cout << std::endl;
}
std::cout << "*****************" << std::endl;
}
void Show(size_t n)
{
std::cout << "*****************" << std::endl;
for (std::vector<T> r : Rows)
{
for (auto& c : r)
std::cout << " " << setw(n) << c;
std::cout << std::endl;
}
std::cout << "*****************" << std::endl;
}
// ~Matrix();
public:
std::vector<std::vector<T>> Rows;
unsigned Rows_count;
unsigned Columns_Count;
};
'''