when we have two values like ID and Marks of a student and we want to put it in a queue we define the priority queue in the following way.
priority_queue<pair<int,int> > queue;
Let us say, that we have four values to put it into a queue. ie., I want all the three values as a single entity in the queue and I will define my own comaprator based on the three values. I'm new to STL and I could not find appropriate way of doing this.
You have std::tuple for such cases. And you write a comparator just like you would write it for a pair.
Joachim's idea of a struct is a good idea. I would probably take it one step further make the struct into its own class (let's call it DataNode). Then you can queue and dequeue the data node objects (each pointing to its own data) rather than passing the raw data into the queue.
#include <iostream>
#include <string>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <functional>
using namespace std;
struct Student
{
Student(string name, int id, int marks): name(name), id(id), marks(marks){}
string name;
int id;
int marks;
};
struct DereferenceCompareNode : public std::binary_function<Student, Student, bool>
{
bool operator()(const Student& lhs, const Student& rhs) const
{
if (lhs.id == rhs.id)
{
return lhs.marks >rhs.marks;
}
else
{
return lhs.id > rhs.id;
}
}
};
int main()
{
priority_queue<Student, vector<Student>, DereferenceCompareNode> a;
a.push(Student("yang", 1000, 98));
a.push(Student("yang", 1000, 75));
a.push(Student("zhang", 999, 98));
a.push(Student("zhang", 999, 100));
while( !a.empty() ){
Student top = a.top();
printf("%s, %d, %d\n", top.name.c_str(), top.id, top.marks);
a.pop();
}
cout<<"hello world"<<endl;
}
Here is the output:
wangyang#wangyang ~ $ ./a.out
zhang, 999, 98
zhang, 999, 100
yang, 1000, 75
yang, 1000, 98
I think you can use this code,
For usage of queue, please refer http://www.cplusplus.com/reference/queue/priority_queue/
Related
I have a struct and some elements in it, I am trying to create a vector of structs and fill it up but tbh im pulling my hair out cause I have no idea what I am doing. Could someone please help me with how I should set this up?
'''
#include <iostream>
#include <string>
#include <vector>
using namespace std;
//define structs
struct animalS
{
string animalType = "none";
int animalCount = 0;
bool animalEndangered = false;
};
int main()
{
vector<animalS> animal;
animal.push_back("" , 0 , true);
}
'''
enter image description here
You have two mistakes, first one your animalS struct doesn't have a constructor, you should add constructor like this:
animalS(const std::string &animalType, int animalCount, bool animalEndangered)
: animalType(animalType)
, animalCount(animalCount)
, animalEndangered(animalEndangered)
{}
And use push_back() like this:
animal.push_back(animalS("" , 0 , true))
im new in c++ (and not to old in programming...) and i have problem with handling vectors and strucs in class.
basically i have a vector and a array of pointers to struct members in the class and i want work on the in my methos but im doing something worng/
here is my movement.h
#pragma once
using namespace std;
class movement
{
private:
static const int MAX_ROW_PER_TRACKER = 100;
static const int MIN_TO_START_CALC = 30;
static const int MAX_TRACKERS = 20;
struct tracker
{
int id;
double a[MAX_ROW_PER_TRACKER];
double b[MAX_ROW_PER_TRACKER];
double c;
};
vector<int> trackersOrder[MAX_TRACKERS] = {};
tracker* trackersArr[MAX_TRACKERS];
public:
movement();
void addRow(int a, int b, int c);
~movement();
};
and my movement.cpp
#include "stdafx.h"
#include "movement.h"
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
movement::movement()
{
}
void movement::addRow(int id, int a, int b)
{
int index;
vector<int>::iterator searchID = find(trackersOrder.begin(), trackersOrder.end(), ID);
if (searchID == trackersOrder.end())
{
vector<int>::iterator freeLocation = find(trackersOrder.begin(), trackersOrder.end(), 0);
index = freeLocation - trackersOrder.begin();
trackersOrder.insert(trackersOrder.begin + index, id);
structArr[index] = new tracker;
structArr[index]->id = id;
structArr[index]->a[0] = a;
structArr[index]->b[0] = b;
structArr[index]->c = 0;
}
}
movement::~movement()
{
}
so when i send to method "addRow" id, and b i want to first check if i allready have this id in my vector (the vector just give me the index for the structs array) and if not then if put the id in the first empty place in the vector and on the structs array/
but from some reasin its look to me that the methid dont reconized the vector and the structs. can you help me understand why?
p.s - i can bet that i have more mistakes in my code, its my firs try with pointers and ect. (im comming from the good life in Matlab) so i will be happy to learn on them also
thank you very much!
The main problem
The problem is that in your code, trackersOrder is not a vector but an array of vectors:
vector<int> trackersOrder[MAX_TRACKERS] = {}; // array of MAXTRACKERS vectors !!
The solution
If you define it as simple vector, it should work better:
vector<int> trackersOrder;
If you want to set its size do it in the movement constructor:
movement::movement() : trackersOrder(MAX_TRACKERS)
{
}
Other issues
There is a case typo with an ID that should be id.
auto searchID = find(trackersOrder.begin(), trackersOrder.end(), id); // by the way auto is easier + ID corrected
There are a missing () after a begin whicn transforms unfortunately your iterator arithmetic into function pointer arithmetic (sic!!):
trackersOrder.insert(trackersOrder.begin() + index, id); // corrected
Finally, there are a couple of structArr that should be replaced by trackersArr.
The result does finally compile (online demo)
If there is a struct:
#include <algorithm>
#include <vector>
#include <iomanip>
#include <string>
using namespace std;
bool pred(string *a, string *b){
return *a < *b;
}
struct Student {
int ID;
int age;
double gpa;
string firstname;
string lastname;
};
int main () {
vector<Student*>v;
vector<Student*>v_sortedFirstName;
//both filled with same information
// sort v_sortedFirstName by first name
sort(v_sortedFirstName.begin(), v_sortedFirstName.end(), pred);
}
Now lets say the vector v is filled with information, and v_sortedFirstName is filled with the same information (points to the same spots as v). How would I (using the STL sort function, sort v_sortedFirstName by firstname?
I was thinking this line: sort(v_sortedFirstName.begin(), v_sortedFirstName.end(), pred);
should be something along the lines of sort(v_sortedFirstName->firstname.begin(), v_sortedFirstName->firstname.end(), pred); but that doesn't work.
Also, if you guys do not mind, I would like to stick with my predicate function above and not use Lambda as I have not learned that yet.
Your predicate has to accept Student * instead of string *:
bool pred(Student *a, Student *b){
return a->firtname < b->firtsname;
}
note if you do not intend to modify data change parameters type to const Student * and that would make your code cleaner and safer (if you put code in pred, that by mistake tries to modify that structure then compiler will reject to compile and it would be easy to detect and fix that mistake):
bool pred(const Student *a, const Student *b){
return a->firtname < b->firtsname;
}
I am creating a sort of very crude hashtable. It will read an ASCII text file and store all the words into a table of linked lists along with the line numbers that word is found. It uses the numerical value of the first letter of the word to find the list to store the word, then searches the list for any entry of the word, if none is found it adds a new entry to the list otherwise it adds the line number to the entry that matches.
I just have no idea how to initialize a vector. It needs 128 lists (one for each ASCII value).
Also note that I am not able to use std::map
I know with a vector of ints you can do vector<int> vector_name(128,0) to get 128 entries all with value 0. I essentially want to do this but with 128 empty lists of entry's.
Here is the code I have so far
#include <iostream>
#include <vector>
#include <cstdlib>
#include <string>
#include <list>
#include <algorithm>
using namespace std;
class index_table {
public:
void insert(string key, int value);
vector<int>& find(string key);
private:
class entry{
public:
string word;
list<int> line_numbers;
};
vector<list<entry> > table;
};
int main(){
return 0;
}
In the constructor that you don't yet have you could do : table.resize(128); now table is a vector of 128 empty std::list's of entry objects.
i.e.
class index_table {
public:
void insert(string key, int value);
vector<int>& find(string key);
//My ctor
index_table(size_t len) : table(len), len(len)
{
//some other stuff someday
}
private:
//not sure why you want to make entry private but ok...
class entry{
public:
string word;
list<int> line_numbers;
};
//some typename convenience for your iterators
typedef entrylist list<entry>;
typedef entrytable vector<entrylist>;
entrytable table;
};
Lets suppose that I have a persons struct:
struct Person {
char name[100];
char surname[100];
unsigned int age;
};
I would like to find out the fastest way to search and find if another struct with the same values (same name, same surname, same age) already exist in a vector.
Please keep in mind that I have million of those in a vector.
Thanks
Here is a possibility:
#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <tuple>
struct Person {
std::string name;
std::string surname;
unsigned int age;
bool operator<(const Person &x) const
{
return std::tie(name, surname, age) < std::tie(x.name, x.surname, x.age);
}
};
int main()
{
std::vector<Person> v;
// ...
std::set<Person> s;
for (const auto &x : v)
{
auto i = s.insert(x);
if (!i.second)
{
// x is duplicated
}
}
}
To your comment, you can sort your vector by this way:
std::sort(v.begin(), v.end()); // Operator < is overloaded
Based on the comments in the question, specifically
No, I mean a set which describes that 10 was duplicate to 2, 12, 54, etc or 2 was duplicate to 10, 12, 54
it sounds like the data structure you actually want is std::multimap (or std::unordered_multimap if you have C++11 and don't care about order). Multimaps will take care of the bookkeeping you would have to do on your own with M M.'s solution (which is nice overall, except that you have to maintain an additional container with duplicate description). std::multimap does the extra bookkeeping for you.
#include <map> // or <unordered_map>
#include <string>
#include <tuple> // std::tie()
#include <utility> // std::make_pair()
struct Person {
std::string name;
std::string surname;
unsigned int age;
bool operator<(const Person &x) const
{
return std::tie(name, surname, age) < std::tie(x.name, x.surname, x.age);
}
};
extern bool tryReadNextPersonFromFile(Person &, size_t & record_id);
int main()
{
std::multimap<Person, size_t> persons;
Person p;
size_t rid;
while(tryReadNextPersonFromFile(p, rid)) {
persons.insert(std::make_pair(p, rid));
}
// ...
p = ...
size_t howMany = persons.count(p);
if(0 == howMany) { /* not found ... */ }
else {
auto eq_range = persons.equal_range(p);
for(auto it=eq_range.first; it != eq_range.second; ++it) {
size_t pRecordID = it->second;
// ...
}
}
}
I'm using a lot of C++11 syntax (like auto) for brevity, but this idea works just as well for C++03. Since you probably haven't heard of multimaps before (or at least are unfamiliar with the STL interface), be sure to check out eg, some documentation on what you can do with it and how.