No matching member function to call for 'push_back' error - c++

While implementing LRU cache got this error.
Earlier I was implementing it via maps it works then but somehow even when doing it as vector it does not work.
#include <list>
class LRUCache {
list<pair<int,int>> lru;
int cap;
vector<list<pair<int, int>>::iterator> hash;
public:
LRUCache(int capacity) {
cap = capacity;
for(int i=0;i<=3000;i++)
hash.push_back(nullptr);
}
int get(int key) {
if(hash[(key)]!=nullptr)
{
int v = hash[key]->first;
lru.erase(hash[key]);
lru.push_front({v,key});
hash[key] = lru.begin();
return v;
}
else
return -1;
}
void put(int key, int value) {
if(hash[(key)]!=nullptr)
{
int v = value;
lru.erase(hash[key]);
lru.push_front({v,key});
hash[key] = lru.begin();
}
else if(lru.size()<cap)
{
lru.push_front({value,key});
hash[key] = lru.begin();
}
else
{
lru.push_front({value,key});
hash[key] = lru.begin();
auto it = lru.end();
it--;
hash[(it->second)] = nullptr;
lru.erase(it);
}
}
};
This way does not work either.
vector<list<pair<int, int>>::iterator> hash(3001,NULL);
Can we not create a vector of pointers?

Create an iterator variable, instead of nullptr value, as bellow:
list<pair<int, int>>::iterator emptyIt; // this iterator object refer to nothing
// Using `emptyIt` to initialize the hash
LRUCache(int capacity) {
cap = capacity;
for(int i=0;i<=3000;i++)
hash.push_back(emptyIt);
}
// Using emptyIt instead of nullptr
int get(int key) {
if(hash[(key)]!=emptyIt)
{
int v = hash[key]->first;
lru.erase(hash[key]);
lru.push_front({v,key});
hash[key] = lru.begin();
return v;
}
else
return -1;
}
void put(int key, int value) {
if(hash[(key)]!=emptyIt)
{
int v = value;
lru.erase(hash[key]);
lru.push_front({v,key});
hash[key] = lru.begin();
}
else if(lru.size()<cap)
{
lru.push_front({value,key});
hash[key] = lru.begin();
}
else
{
lru.push_front({value,key});
hash[key] = lru.begin();
auto it = lru.end();
it--;
hash[(it->second)] = emptyIt;
lru.erase(it);
}
}
};

Related

Maximum Sort of a Simple One-way List

I'm trying to do the Maximum Sort of a Simple One-way List. However my program has some bugs in it, which I can't figure out what it is.
It behaves strange because sometimes it works well to a point where it just stop working but i see return 0 (for example: I give the list of 1234 and I get back 3412), sometimes it working to a point, then goes to an infinte loop. (for example: case of 12345 it put 5, 4 and 3 the the 1st place and then infinite loop).
The problem is probably in the list::remMax() or in the maxRend().
My code:
struct chain
{
char key;
chain *next;
};
/////////////////////////////////////////////
class list
{
private:
chain *L, **act;
public:
list() {
L=NULL;
act=&L;
}
~list() {
chain *p;
while(L) {
p=L;
L=L->next;
delete []p;
}
}
enum ERROR {endErr, memErr};
void first() {act=&L;};
void next() {
if(*act!=NULL) {
act=&(*act)->next;
} else throw endErr;
}
bool end() {return *act==NULL;}
bool oneEIn() {return L->next==NULL;} //list contains only 1 element
bool twoEIn() {return L->next->next==NULL;} //list contains 2 elements
void addE(char x) {
chain *p=new(nothrow) chain;
if(p == NULL) throw memErr;
p->key=x;
p->next=*act;
*act=p;
}
chain* remMax(chain *H) {
if(!oneEIn()) {
chain *qe, *q, *Mpe, *Mp;
if(twoEIn()) {
Mp = H;
q = Mp->next;
if(q->key > Mp->key) {
Mp->next=q->next;
return q;
} else {
H=q;
Mp->next=NULL;
return Mp;
}
} else {
Mp=H;
q=Mp->next;
Mpe = H;
qe = Mp;
while(q != NULL) {
if(Mpe->key > Mp->key) Mp = Mpe;
if(q->key > Mp->key) {
Mp=q;
Mpe=qe;
}
qe=q;
q=q->next;
}
if(Mpe == Mp) H=Mp->next;
else {
Mpe->next = Mp->next;
}
Mp->next=NULL;
return Mp;
}
} else {
chain *Mp;
Mp = H;
H = NULL;
return Mp;
}
}
void inE(chain *Mp) {
first();
Mp->next = *act;
addE(Mp->key);
}
chain* getFirst() {return L;}
void printList() {
chain *p=L;
while(p != NULL) {
putchar(p->key);
p=p->next;
}
}
};
///////////////////////////////////
void makeList(list& L) {
char c;
while((c=getchar())!='\n') {
L.addE(c);
L.next();
}
}
void maxRend(list& L) {
if(!L.oneEIn()) {
chain *H, *Mp;
H=L.getFirst();
while(H != NULL) {
cout<<"1.while\n";
Mp = L.remMax(H);
L.inE(Mp);
cout<<"putIn: "<<Mp->key<<endl;
H=H->next;
L.printList();
cout<<endl;
}
cout<<"\nSorted list: ";
L.printList();
} else L.printList();
}
//////////////////////////////////////////////
int main()
{
list L;
makeList(L);
maxRend(L);
return 0;
}

Custom Iterator to pretend element is in vector

A class of element used to be stored in a vector with other similar elements.
But now, it been removed and moved into its own field in the parent object.
class OldParent {
vector<char> OldCollection = { 'A', 'B', 'C' };
}
class NewParent {
char A = 'A';
vector<char> NewCollection = { 'B', 'C' };
}
The type that is held by the vector is significantly more complicated than a character, it is a vector of a normalish struct.
So the actual original type would look something like this:
struct ActualType {
string val1;
int val2;
double val3;
}
vector<vector<ActualType>> OldCollection;
// vector that has been separated out
vector<ActualType> SeparatedCollection;
The problem is that alot of the original code uses iterators over the whole old collection and a clean way I thought I could implement this change would be to create an iterator that would work as if the separated field was never separated. This way much of the original code would not have to be changed.
However, I am definitely open to new ideas as well.
The use case looks like this:
The change means that one of the numbers will be permanently stored outside of the vector.
vector<int> nNums = {1,2,3};
void UseCase(int x)
{
int toRemove = 0;
for (auto& num : nNums)
{
if (num - x < 0)
{
toRemove++;
x -= num;
}
else
{
num -= x;
break;
}
for (int i = 0; i < toRemove; ++i)
nNums.erase(nNums.begin());
}
}
Here's a demo for a custom container that will take pointers to both the separated object and the container for the rest of the objects:
#include <vector>
#include <iostream>
#include <cmath>
template <typename T>
class CustomIterator;
template <typename T>
class CustomContainer
{
public:
CustomContainer(std::vector<T> *container, T *separated) : mContainer{container},
mSeparated{separated} {}
std::vector<T> *GetContainer() { return mContainer; }
T *GetSeparated() { return mSeparated; }
inline CustomIterator<T> begin() { return CustomIterator<T>(this); }
inline CustomIterator<T> end() { return CustomIterator<T>(this, mContainer->size() + 1); }
private:
std::vector<T> *mContainer;
T *mSeparated;
};
template <typename T>
class CustomIterator
{
public:
CustomIterator(CustomContainer<T> *container) : mCustomContainer{container}, mPos{0} {}
CustomIterator(CustomContainer<T> *container, int pos) : mCustomContainer{container}, mPos(pos) {}
CustomIterator(const CustomIterator<T> &other) = default;
const CustomContainer<T> *GetContainer() const { return mCustomContainer; }
const int GetPos() const { return mPos; }
~CustomIterator() {}
CustomIterator<T> &operator=(const CustomIterator<T> other)
{
mCustomContainer = other.GetContainer();
mPos = other.GetPos();
};
bool operator==(const CustomIterator<T> &other) { return other.GetContainer() == mCustomContainer && other.mPos == mPos; }
bool operator!=(const CustomIterator<T> &other) { return other.GetContainer() != mCustomContainer || other.mPos != mPos; }
CustomIterator<T> operator+=(const int &movement)
{
if (mPos + movement > mCustomContainer->GetContainer()->size() + 1)
mPos = mCustomContainer->GetContainer()->size() + 1;
else
mPos += movement;
return CustomIterator<T>(*this);
}
CustomIterator<T> operator-=(const int &movement)
{
if (mPos - movement < 0)
mPos = 0;
else
mPos -= movement;
return CustomIterator<T>(*this);
}
CustomIterator<T> operator++()
{
const auto maxSize = mCustomContainer->GetContainer()->size() + 1;
mPos = mPos == maxSize ? maxSize : mPos + 1;
return CustomIterator<T>(*this);
}
CustomIterator<T> operator--()
{
mPos = mPos == 0 ? 0 : mPos - 1;
return CustomIterator<T>(*this);
}
int operator-(const CustomIterator<T> &other) { return std::abs(other.GetPos() - mPos); }
T &operator*()
{
const auto maxSize = mCustomContainer->GetContainer()->size() + 1;
if (mPos == maxSize)
{
throw "Error: index out of bounds";
}
else if (mPos == 0)
{
return *(mCustomContainer->GetSeparated());
}
return (*mCustomContainer->GetContainer()).at(mPos - 1);
}
T &operator->() { this->operator*(); }
private:
CustomContainer<T> *mCustomContainer;
int mPos;
};
int main()
{
std::vector<int> container = {5, 6};
int separated = 4;
auto customContainer = CustomContainer<int>(&container, &separated);
for (auto i : customContainer)
{
std::cout << (i) << std::endl;
}
return 0;
}

Disjoint set data structure : track size of each tree

Below is my implementation to keep track of the size of each tree in the disjoint set forest.
Can you please tell me what is wrong with it ? I am trying to solve UVa problem https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3638
#include <iostream>
#include <cstdio>
#include <unordered_map>
using namespace std;
class Node {
public :
int id;
Node *parent;
unsigned long long rank;
Node(int id) {
this->id = id;
// this->data = data;
this->rank =1; //size here
this->parent = this;
}
friend class DisjointSet;
};
class DisjointSet {
unordered_map<int,Node*> nodesMap;
Node *find_set_helper(Node *aNode) {
if (aNode == aNode->parent) {
return aNode->parent;
}
return find_set_helper(aNode->parent);
}
void link(Node *xNode,Node *yNode) {
if( xNode->rank > yNode->rank) {
yNode->parent = xNode;
xNode->rank += yNode->rank;
}
// else if(xNode-> rank < yNode->rank){
// xNode->parent = yNode;
// yNode->rank += xNode->rank;
// }
else {
xNode->parent = yNode;
yNode->rank += xNode->rank;
}
}
public:
DisjointSet() {
}
void AddElements(int sz) {
for(int i=0;i<sz;i++)
this->make_set(i);
}
void make_set(int id) {
Node *aNode = new Node(id);
this->nodesMap.insert(make_pair(id,aNode));
}
void Union(int xId, int yId) {
Node *xNode = find_set(xId);
Node *yNode = find_set(yId);
if(xNode && yNode)
link(xNode,yNode);
}
Node* find_set(int id) {
unordered_map<int,Node*> :: iterator itr = this->nodesMap.find(id);
if(itr == this->nodesMap.end())
return NULL;
return this->find_set_helper(itr->second);
}
~DisjointSet(){
unordered_map<int,Node*>::iterator itr;
for(itr = nodesMap.begin(); itr != nodesMap.end(); itr++) {
delete (itr->second);
}
}
};
int main() {
int n,m,k,first,cur;
//freopen("in.in","r",stdin);
scanf("%d %d",&n,&m);
while(n != 0 || m != 0) {
DisjointSet *ds = new DisjointSet();
ds->AddElements(n); // 0 to n-1
//printf("\n n = %d m = %d",n,m);
for(int i=1;i<=m;i++) {
scanf("%d",&k);
//printf("\nk=%d",k);
if ( k > 0 ) {
scanf("%d",&first);
for(int j=2;j<=k;j++) {
scanf("%d",&cur);
ds->Union(first,cur);
}
}
}
Node *zeroSet = ds->find_set(0);
// unsigned long long count = ds->getCount(zeroSet->id);
printf("%llu\n",zeroSet->rank);
delete ds;
scanf("%d %d",&n,&m);
}
return 0;
}
The link function in the above code does the job of updating the tree size.
The solution to the problem is to find the set which elements 0 belongs to and get the size of the representative element of the set.
But I am getting wrong answer with this code.
Can you please help me
In your Union function, check if both nodes are already in the same set.
if(xNode && yNode && xNode != yNode)
link(xNode,yNode);

Algorithm for graph post dominance?

What algorithm can be used to calculate post dominators in a control flow graph?
Currently I calculate the dominators by using the iterative bit vector algorithm:
#include <iostream>
#include <list>
#include <stack>
#include <vector>
#include <memory>
#include <map>
class BasicBlock
{
public:
BasicBlock(std::string name) : mName(name) { }
void AllocateDominatorsAndSetToTrue(const size_t nBlocks)
{
mDominators.resize(nBlocks);
for (size_t i = 0; i < nBlocks; i++)
{
mDominators[i] = true;
}
}
void SetAllDominatorsTo(bool value)
{
for (size_t i = 0; i < mDominators.size(); i++)
{
mDominators[i] = value;
}
}
std::string mName;
int mId = 0;
// Links to blocks before this one
std::vector<BasicBlock*> mPredecessors;
// Links to blocks after this one
std::vector<BasicBlock*> mSucessors;
std::vector<bool> mDominators;
std::vector<BasicBlock*> mImmediateDominator;
};
class ControlFlowGraph
{
public:
void AddBasicBlock(std::string name)
{
mBasicBlocks.emplace_back(std::make_unique<BasicBlock>(name));
}
void AddSucessor(std::string block, std::string target)
{
FindBlock(block)->mSucessors.emplace_back(FindBlock(target));
}
void AddPredecessor(std::string block, std::string target)
{
FindBlock(block)->mPredecessors.emplace_back(FindBlock(target));
}
BasicBlock* FindBlock(std::string name)
{
for (const auto& block : mBasicBlocks)
{
if (block->mName == name)
{
return block.get();
}
}
return nullptr;
}
void CalculateDominators()
{
const size_t nBlocks = mBasicBlocks.size();
int i = 0;
for (std::unique_ptr<BasicBlock>& block : mBasicBlocks)
{
block->mId = i++;
block->AllocateDominatorsAndSetToTrue(nBlocks);
}
BasicBlock* block = mBasicBlocks[0].get();
block->SetAllDominatorsTo(false);
block->mDominators[block->mId] = true; // block always dominates itself
bool changed = false;
do
{
changed = false;
for (std::unique_ptr<BasicBlock>& b : mBasicBlocks)
{
if (b == mBasicBlocks[0]) // Is it the entry node?
{
continue;
}
for (BasicBlock* pred : b->mPredecessors)
{
auto T = b->mDominators;
for (size_t i = 0; i < nBlocks; i++)
{
if (b->mDominators[i] && pred->mDominators[i])
{
b->mDominators[i] = true;
}
else
{
b->mDominators[i] = false;
}
}
b->mDominators[b->mId] = true; // block always dominates itself
if (b->mDominators != T)
{
changed = true;
}
}
}
}
while (changed);
}
void CalculateImmediateDominators()
{
// ??
}
std::vector<std::unique_ptr<BasicBlock>> mBasicBlocks;
};
int main()
{
ControlFlowGraph graph;
graph.AddBasicBlock("1");
graph.AddBasicBlock("2");
graph.AddBasicBlock("3");
graph.AddBasicBlock("4");
graph.AddBasicBlock("5");
graph.AddBasicBlock("6");
graph.AddSucessor("1", "2");
graph.AddSucessor("2", "3");
graph.AddSucessor("2", "4");
graph.AddSucessor("3", "2");
graph.AddSucessor("4", "5");
graph.AddSucessor("4", "6");
graph.AddSucessor("5", "4");
graph.AddSucessor("6", "2");
graph.AddPredecessor("2", "1");
graph.AddPredecessor("3", "2");
graph.AddPredecessor("4", "2");
graph.AddPredecessor("5", "4");
graph.AddPredecessor("6", "4");
graph.CalculateDominators();
graph.CalculateImmediateDominators();
return 0;
}

Cref postincrementation in Map definition

So I have such definition on map class on vector, it works good except for post-incrementation, which doesn't work as it should. You can see in example that variable a should be equal to 10 (post-incremented after assignment). But it's equal to 11. I have no idea how to fix that.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
template<class T>
class Map {
class Cref {
friend class Map;
Map& m;
string key;
T value;
public:
operator double() {
return m.read(key);
};
Map::Cref & operator=(double num) {
m.write(key, num);
return *this;
};
Map::Cref & operator++(int) {
Cref c(*this);
m.increment(key, value);
return c;
}
Cref(Map& m, string a)
: m(m),
key(a) {};
};
public:
class Unitialized {};
struct Record {
string key;
T value;
};
vector<Record> data;
Map() {}
~Map() {}
bool ifexist(string k) {
for (int i = 0; i < data.size(); i++) {
if (data.at(i).key == k)
return 1;
}
return 0;
}
Cref operator[](string key) {
return Map::Cref( * this, key);
}
private:
void increment(string key, T value) {
if (ifexist(key) == 0) {
throw Unitialized();
}
for (int i = 0; i < data.size(); i++) {
if (data.at(i).key == key)
data.at(i).value += 1;
}
}
void write(string key, T value) {
if (ifexist(key) == 1) {
cout << "Element already exist" << endl;
return;
}
Record r;
r.key = key;
r.value = value;
data.push_back(r);
}
double read(string key) {
if (ifexist(key) == 0) {
throw Unitialized();
}
for (int i = 0; i < data.size(); i++) {
if (data.at(i).key == key)
return data.at(i).value;
}
return 0;
}
};
int main(int argc, char** argv) {
Map<int> m;
m["ala"] = 10;
int a = 0;
a = m["ala"]++;
cout << a << endl;
try {
cout << m["ala"] << endl;
cout << m["ola"] << endl;
} catch (Map<int>::Unitialized&) {
cout << "Unitialized element" << endl;
}
return 0;
}
Yes, I already fixed that, overloading of ++ operator should look like that :
T operator ++(int)
{
T ret = m.read(this->key);
m.increment(key, value);
return ret;
}
This fixes everything.