how many nodes in graph are reachable? - c++

I want to print the number of nodes which are reachable from a particular node. I read graph and stored in adjacency list and performed bfs.i had tried the following code.it works with certain graph.can you traced out what's wrong with this?
#include <vector>
#include <iostream>
#include <list>
#include<queue>
using namespace std;
int BFS(int s)
{
const int V=100;
int r=0;
vector<list<int> > a(V);
int visited[V]={0};
queue<int> Q;
visited[s]=1;
Q.push(s);
++r;
while(!Q.empty())
{
int x=Q.front();
Q.pop(); // pop here. we have x now
++r;
vector<list<int> >::iterator it1=a.begin()+x;
list<int> it2=*it1;
list<int>::iterator iter=it2.begin();
while(iter!=it2.end())
{
if(visited[*iter]==0)
{
visited[*iter]=1;
Q.push(*iter);
}
++iter;
}
visited[x]=2; // set visited here.
}
return r;
}
void printAsGrid(int V)
{
// Create a local 2D projection grid
int size = V.size();
double *grid = new double[size*size];
memset(grid, 0.0, size*size*sizeof(double));
// Get the edge connection and weight
int index;
for (index = 0; index < size; index++) {
list<Edge>::const_iterator eit;
for (eit = V[index].edges.begin();
eit != V[index].edges.end(); eit++) {
int to = (*eit).to;
double w = (*eit).weight;
// record weight in the projection grid
grid[(index*size)+to] = w;
}
}
// print header
out << " |";
for (index = 0; index < size; index++)
out << " " << index;
out << endl;
out << "---+";
for (index = 0; index < size; index++)
out << "-----";
out << endl;
// print content
out.setf(ios::fixed);
out.setf(ios::showpoint);
for (index = 0; index < size; index++) {
out << " " << index << " |";
for (int j = 0; j < size; ++j)
out << setw(5) << setprecision(1) << grid[(index*size)+j];
out << endl;
}
// delete grid before exit
delete [] grid;
}
int main()
{
int s;
int V,total_neighbors, id, weight;
//number of vertices
cout<<"enter the no.of vertices:";
cin>>V;
vector< list< int > > graph(V + 1);
for(int i= 0; i<V;i++) {
cout<<"Enter no.of neighbours of"<<i<<":";
cin>>total_neighbors;
cout<<"Enter the neighbours of"<<i<<":";
for(int j = 0; j <total_neighbors; j++) {
cin>>id;
graph[i].push_back(id);
}
}
vector<list<int> >::iterator i;
int c=0;
for (vector<std::list<int> >::iterator i=graph.begin(); i !=graph.end(); ++i){
cout<<"vertices connected to node "<<c <<" are ";
//cout<<*i;
std::list<int> li = *i;
for(std::list<int>::iterator iter = li.begin(); iter!= li.end(); ++iter){
cout<<*iter<<" ";
}
cout<<endl;
c++;
}
int f;
cin>>f;
s=BFS(f);
cout<<s<<" ";
return 0;
}
adjacencyList 0 -> 1 -> 2
adjacencyList 1 -> 2 -> 4
adjacencyList 2 -> 4
adjacencyList 3 -> 5
adjacencyList 4
adjacencyList 5 -> 3
returns 2 but actual answer is 3

You are doing r++ two times. You can do it only when you are pushing the node or when just popping the node. Otherwise for the source node, it will count twice. Also initialise r to 0. Also initialise the visited array manually to be on safe side.
Also you have taken vector<list<int> >::iterator it1=a.begin()+x; whereas a is empty. vector<list<int> > a(V); just initialises the vector of list but doesn't put values inside it. And hence the list which you are trying to traverse is empty. You are getting 2 because you are making r++ two times . One when source is inserted and other when source is removed which gives you 2.
See this code :
#include <vector>
#include <iostream>
#include <list>
#include<queue>
using namespace std;
int BFS(vector<list<int> > graph, int s)
{
const int V=100;
int r=0;
int visited[V]={0};
for(int i = 0; i < V; i++) visited[i] = 0;
queue<int> Q;
visited[s]=1;
Q.push(s);
while(!Q.empty())
{
int x=Q.front();
cout << x << endl;
Q.pop(); // pop here. we have x now
++r;
vector<list<int> >::iterator it1=graph.begin()+x;
list<int> it2=*it1;
list<int>::iterator iter=it2.begin();
while(iter!=it2.end())
{
if(visited[*iter]==0)
{
visited[*iter]=1;
Q.push(*iter);
}
++iter;
}
visited[x]=2; // set visited here.
}
return r;
}
int main()
{
int s;
int V,total_neighbors, id, weight;
//number of vertices
cout<<"enter the no.of vertices:";
cin>>V;
vector< list< int > > graph(V + 1);
for(int i= 0; i<V;i++) {
cout<<"Enter no.of neighbours of"<<i<<":";
cin>>total_neighbors;
cout<<"Enter the neighbours of"<<i<<":";
for(int j = 0; j <total_neighbors; j++) {
cin>>id;
graph[i].push_back(id);
}
}
vector<list<int> >::iterator i;
int c=0;
for (vector<std::list<int> >::iterator i=graph.begin(); i !=graph.end(); ++i){
cout<<"vertices connected to node "<<c <<" are ";
//cout<<*i;
std::list<int> li = *i;
for(std::list<int>::iterator iter = li.begin(); iter!= li.end(); ++iter){
cout<<*iter<<" ";
}
cout<<endl;
c++;
}
int f;
cin>>f;
s=BFS(graph,f);
cout<<s<<" ";
return 0;
}

Related

How to display minimum spannign tree matrix

#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.

Identical .txt files w/ different outputs

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();
}

Directed Acyclical Graph Crash

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;
}

C++ unable to find multiple modes

My assignment asks me to write a function that takes an array and the size of that array as a parameter, and to find the mode. If there are multiple modes, I am to find them all, and place them in a vector and print said vector in an ascending order.
For example, if I input the following integers:
3, 4, 2, 1, 2, 3
Then the output should display
2, 3
If I input the following integers:
1, 2, 3, 4
Then the output should display:
1, 2, 3, 4.
However, my program somehow only finds the first mode and displays it in a really awkward manner.
Here was my input:
3, 4, 2, 3, 2, 1
And this was the output:
3
3
3
3
3
Here is my code. Any help would be greatly appreciated. Thank you all for your time!
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
int size; //array size
int* array; //array of ints
int arraycount; //counter for array loop
void findMode(int array[], int size); //function prototype
//intialize array
cout << "Enter number of integers ";
cout << "you wish to input." << endl;
cin >> size;
cout << "Enter the integers." << endl;
array = new int[size];
for (arraycount = 0; arraycount < size;
arraycount++)
cin >> array[arraycount];
//call function
findMode(array, size);
return 0;
}
void findMode(int array[], int size) {
int counter = 1;
int max = 0;
int mode = array[0];
int count;
vector <int> results;
//find modes
for(int pass = 0; pass < size - 1; pass++) {
if(array[pass] == array[pass+1]) {
counter++;
if(counter > max) {
max = counter;
mode = array[pass];
}
}
else {
counter = 1;
}
}
//push results to vector
for (count=0; count < size - 1; count++) {
if(counter == max) {
std::cin >> mode;
results.push_back(mode);
}
}
//sort vector and print
std::sort(results.begin(), results.end());
for (count=0; count < size - 1; count++) {
cout << mode << endl;
}
}
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <map>
using namespace std;
int main() {
int size; //array size
int* array; //array of ints
std::vector<int> vecInput;
int arraycount; //counter for array loop
void findMode(std::vector<int> vec); //function prototype
//intialize array
cout << "Enter number of integers ";
cout << "you wish to input." << endl;
cin >> size;
cout << "Enter the integers." << endl;
array = new int[size];
for (arraycount = 0; arraycount < size; arraycount++)
{
int num;
cin >> num;
vecInput.push_back(num);
}
//call function
findMode(vecInput);
return 0;
}
void findMode(std::vector<int> vec)
{
std::sort(vec.begin(), vec.end());
std::map<int, int> modMap;
std::vector<int>::iterator iter = vec.begin();
std::vector<int> results;
int prev = *iter;
int maxCount = 1;
modMap.insert(std::pair <int,int>(*iter, 1));
iter++;
for (; iter!= vec.end(); iter++)
{
if (prev == *iter)
{
std::map<int, int>::iterator mapiter = modMap.find(*iter);
if ( mapiter == modMap.end())
{
modMap.insert(std::pair <int,int>(*iter, 1));
}
else
{
mapiter->second++;
if (mapiter->second > maxCount)
{
maxCount = mapiter->second;
}
}
}
else
{
modMap.insert(std::pair <int,int>(*iter, 1));
}
prev = *iter;
}
std::map<int, int>::iterator mapIter = modMap.begin();
for (; mapIter != modMap.end(); mapIter++)
{
if (mapIter->second == maxCount)
{
results.push_back(mapIter->first);
}
}
cout << "mod values are " <<endl;
std::vector<int>::iterator vecIter = results.begin();
for (; vecIter != results.end(); vecIter++)
cout<<*vecIter<<endl;
}
Thank you all for the help, I was able to get the code to work. Turns out the problem was the cin in my vector portion of the function. Here is my revised code:
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <stdlib.h>
#include <vector>
using namespace std;
#define N 100
void findMode(int x[], int size); //function prototype
vector<int> results; //vector
int main(void) {
int* x;
int size=0;
int arraycount;
//intialize array
cout << "Enter number of integers ";
cout << "you wish to input." << endl;
cin >> size;
cout << "Enter the integers." << endl;
x = new int[size];
for (arraycount = 0; arraycount < size;
arraycount++)
cin >> x[arraycount];
//send array and size to function
findMode(x, size);
return 0;
}
//findMode function
void findMode(int x[], int size) {
int y[N]={0};
int i, j, k, m, cnt, count, max=0;
int mode_cnt=0;
int num;
int v;
vector<int> results;
vector<int>::iterator pos;
//loop to count an array from left to right
for(k=0; k<size; k++) {
cnt=0;
num=x[k]; //num will equal the value of x[k]
for(i=k; i<size; i++) {
if(num==x[i])
cnt++;
}
y[k]=cnt; //
}
//find highest number in array
for(j=0; j<size; j++) {
if(y[j]>max)
max=y[j];
}
//find how many modes there are
for(m=0; m<size; m++) {
if(max==y[m])
mode_cnt++;
}
//push results to vector
for (m=0; m < size; m++) {
if(max == y[m]) {
//after taking out this line the code works properly
// std::cin >> x[m];
results.push_back(x[m]);
}
}
//sort vector and print
std::sort(results.begin(), results.end());
cout << "The mode(s) is/are: ";
for (pos=results.begin(); pos!=results.end(); ++pos) {
cout << *pos << " ";
}
}

Sorting Structs and Arrays

My task is to read in a file with names and scores for a game (file looks something like)
5
John Doe 200
Chris Brown 340
Chris Brown 320
John Smith 300
John Doe 600
And prints out the names in alphabetical order (last name) with the highest score from that person. So output would look something like:
Chris Brown 340
John Doe 600
John Smith 300
I figured out how to sort and print the scores from highest to lowest, but I'm lost on how to print out just the highest scores from each person... any help would be appreciated!
#include <iostream>
#include <fstream>
using namespace std;
struct playerscore
{
string first, last;
int score;
};
bool score(playerscore a, playerscore b);
void selectionsort(playerscore *A, int n);
int main()
{
string file;
int n;
cin >> file;
ifstream fin(file.c_str());
fin >> n;
// read in the names and the scores in the form of struct playerscore
playerscore *A = new playerscore[n];
for(int i = 0; i < n; i++)
fin >> A[i].first >> A[i].last >> A[i].score;
// sort the data
selectionsort(A, n);
// print in sorted order
for(int i = 0; i < n; i++)
cout << A[i].score << " ";
cout << endl;
return 0;
}
bool before(playerscore a, playerscore b)
{
return a.score > b.score;
}
void selectionsort(playerscore *A, int n)
{
for(int length = n; length > 1; length--)
{
//find imax, index of largest
int imax = 0, i;
for(i = 1; i < length; i++)
if(before(A[imax], A[i]))
imax = i;
// swap A[imax] and the last element
playerscore temp = A[imax];
A[imax] = A[length-1];
A[length-1] = temp;
}
}
Sort to ascending order of the name.
If the names compared are same, element with higher score should be come to earlier position of the array.
Print the first element and elements whose name differs from previous element.
Sample implementation:
#include <iostream>
#include <fstream>
using namespace std;
struct playerscore
{
string first, last;
int score;
};
bool score(playerscore a, playerscore b);
void selectionsort(playerscore *A, int n);
int main()
{
string file;
int n;
#if 0
cin >> file;
ifstream fin(file.c_str());
#else
#define fin cin // to test with online compiler
#endif
fin >> n;
// read in the names and the scores in the form of struct playerscore
playerscore *A = new playerscore[n];
for(int i = 0; i < n; i++)
fin >> A[i].first >> A[i].last >> A[i].score;
// sort the data
selectionsort(A, n);
// print in sorted order
for(int i = 0; i < n; i++)
if (i == 0 || A[i].first != A[i - 1].first || A[i].last != A[i - 1].last)
cout << A[i].first << " " << A[i].last << " " << A[i].score << "\n";
cout << endl;
return 0;
}
bool before(playerscore a, playerscore b)
{
return a.first == b.first ? (a.last == b.last ? a.score > b.score : a.last < b.last) : a.first < b.first;
}
void selectionsort(playerscore *A, int n)
{
for(int length = n; length > 1; length--)
{
//find imax, index of largest
int imax = 0, i;
for(i = 1; i < length; i++)
if(before(A[imax], A[i]))
imax = i;
// swap A[imax] and the last element
playerscore temp = A[imax];
A[imax] = A[length-1];
A[length-1] = temp;
}
}
You've already done the difficult part.
Suppose the ((first, last), score) pairs are already sorted, the highest score for each player is the first record for this player, so just keep the current player's name as curr_name when you visit the array:
If the next name is same as curr_name, you can safely ignore this item.
If not, print this record, and update curr_name.
The code is like blew:
#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <string>
#include <utility>
using namespace std;
bool mycmp (pair<pair<string, string>, int> a, pair<pair<string, string>, int> b) {
return a.first < b.first || (a.first == b.first && a.second > b.second);
}
int main(int argc, char *argv[])
{
ifstream fin("data.txt");
int n;
fin>>n;
vector<pair<pair<string, string>, int>> A(n);
for(int i = 0; i < n; ++i){
fin>>A[i].first.first>>A[i].first.second>>A[i].second;
}
sort(A.begin(), A.end(), mycmp);
pair<string, string> cur_name;
for(int i = 0; i < n; ++i){
if(cur_name != A[i].first){
cout<<A[i].first.first<<" "<<A[i].first.second<<" "<<A[i].second<<endl;
cur_name = A[i].first;
}
}
return 0;
}
As pointed out before, since it's a task I decided to rewrite the code and it should now look like this.
Sort the array based on the score
Sort the array based on alphabetical order
Print unique entries
#include <iostream>
#include <fstream>
using namespace std;
struct playerscore
{
string first, last;
int score;
};
bool score(playerscore a, playerscore b);
void selectionsort(playerscore *A, int n);
int main()
{
string file;
int n;
cin >> file;
ifstream fin(file.c_str());
fin >> n;
// read in the names and the scores in the form of struct playerscore
playerscore *A = new playerscore[n];
for (int i = 0; i < n; i++)
fin >> A[i].first >> A[i].last >> A[i].score;
// sort the data
selectionsort(A, n);
// sort alphabetically and print unique entries
for (int i=0; i<n-1; i++)
{
for (int j=i+1; j<n; j++)
{
if (A[j].last <= A[i].last && A[j].first < A[i].first)
{
playerscore tmp = A[i];
A[i] = A[j], A[j] = tmp;
}
}
playerscore max;
int j = 0;
for (int i=0; j+i<n; i++)
{
max.score = -1;
while (j+i<n && A[j+i].last == A[i].last && A[j+i].first == A[i].first)
{
if (A[j+i].score >= A[i].score)
max = A[j+i];
j++;
}
j--;
if (max.score >= 0)
cout << max.last << " " << max.first << " " << max.score << endl;
}
cout << endl;
return 0;
}
bool before(playerscore a, playerscore b)
{
return a.score > b.score;
}
void selectionsort(playerscore *A, int n)
{
for(int length = n; length > 1; length--)
{
//find imax, index of largest
int imax = 0, i;
for(i = 1; i < length; i++)
if(before(A[imax], A[i]))
imax = i;
// swap A[imax] and the last element
playerscore temp = A[imax];
A[imax] = A[length-1];
A[length-1] = temp;
}
}