I have a working implementation for the classic "Queue using two stacks" data structure in C++ and am wondering what the best software engineering practice would be for handling const correctness.
The peek() function returns the value at the front of the queue, which may mean that we need to pop everything from one stack and copy it to the other. One way to use the copy function is to cast the constness away for this as shewn below. Is there a better way?
class MyQueue {
stack <int> s1;
stack <int> s2;
public:
MyQueue() {
}
void push(int x) {
s1.push(x);
}
void copy()
{
while (!s1.empty()) {
s2.push(s1.top());
s1.pop();
}
}
int pop() {
int res;
if (s2.empty()) copy();
if (! s2.empty()) {
res = s2.top();
s2.pop();
}
return res;
}
int peek() const {
if (s2.empty()) ((MyQueue*) (this))->copy();
return s2.top();
}
bool empty() const {
return s1.empty() && s2.empty();
}
};
It's better to adjust the design a bit, so that s2 is never empty unless the queue is empty. Then the difficult question goes away, and the code gets simpler, too:
class MyQueue {
stack <int> s1;
stack <int> s2;
public:
MyQueue() {
}
void push(int x) {
if (s2.empty()) {
// queue is empty
s2.push(x);
} else {
s1.push(x);
}
}
int pop() {
int res = s2.pop();
if (s2.empty())
copy();
return res;
}
int peek() const {
return s2.top();
}
bool empty() const {
return s2.empty();
}
private:
void copy()
{
while (!s1.empty()) {
s2.push(s1.pop());
}
}
};
Related
class
{
public:
void func(const int val, const bool flag)
{
if(flag)
{
while(!lower.empty() && val <= lower.top())
{
// do a bunch of stuff with lower
}
}
else
{
while(!higher.empty() && val >= higher.top())
{
// do a bunch of stuff with higher, but it's the same stuff as would've done
// for lower
}
}
}
private:
std::stack<int> lower;
std::stack<int> higher;
}
I'm trying to figure out a better way to write the clauses because currently, I have a lot of duplicate code in both. The only difference is one clause operates on lower and the other on higher and the <= in the first clause is changed to >= higher in the second one.
I could wrap the clause in a helper function and call it in each clause (and pass in the lower and higher as an argument), e.g.,
class
{
public:
void func(const int val, const bool flag)
{
if(flag)
{
helper(lower, comparer);
}
else
{
helper(lower, comparer);
}
}
void helper(std::stack<int> &st)
{
// do a bunch of stuff with st
}
private:
std::stack<int> lower;
std::stack<int> higher;
}
I'm not sure if this is a good idea and if it is, I'm not sure how to get around the >= vs. <=. I'm hoping for suggestions on my design!
You can do something like the following:
class
{
public:
void func(const int val, const bool flag)
{
std::stack<int> *st;
bool (*compare)(int, int);
if (flag)
{
st = &lower;
compare = [](int a, int b){ return a <= b; };
}
else
{
st = &higher;
compare = [](int a, int b){ return a >= b; };
}
while (!st->empty() && compare(val, st->top()))
{
// do a bunch of stuff with *st
}
}
private:
std::stack<int> lower;
std::stack<int> higher;
}
Alternatively, using a helper would certainly work, too:
class
{
public:
void func(const int val, const bool flag)
{
if (flag)
func_helper(lower, val, std::less_equal{});
else
func_helper(higher, val, std::greater_equal{});
}
private:
std::stack<int> lower;
std::stack<int> higher;
template<typename Comparer>
void func_helper(stack<int> &st, const int val, Comparer compare)
{
while (!st.empty() && compare(val, st.top()))
{
// do a bunch of stuff with st
}
}
}
How about something like this
class
{
public:
void func(const int val, const bool flag)
{
int sign = 1;
std::stack<int>* higher_or_lower = &higher;
if(flag)
{
higher_or_lower = &lower;
sign = -1;
}
while(!higher_or_lower->empty() && sign*val >= sign*higher_or_lower->top())
{
// do a bunch of stuff with higher_or_lower
}
}
private:
std::stack<int> lower;
std::stack<int> higher;
}
The higher_or_lower covers both stacks and the sign takes care of less than vs. greater than.
Or a bit more compact:
class C
{
public:
void func(const int val, const bool flag)
{
const std::stack<int>* st[] = {&lower, &higher};
bool (*compare[])(int, int) = { [](int a, int b) { return a <= b; } , [](int a, int b) { return a >= b; } };
while (!st[flag]->empty() && compare[flag](val, st[flag]->top()))
{
// do a bunch of stuff with *st
}
}
private:
std::stack<int> lower;
std::stack<int> higher;
};
Im writing a program that simulates a vacuum cleaning a room. There is an initial state of dirty spots and I want to use various AI algorithms to find the best paths to clean the room. By making the algorithms separate from the actual problem I think my solution will be very modular.
Each algorithm only knows about States. Each state can be expanded to children states. Here is my first algorithm, UniformCost:
#include<iostream>
#include<set>
class State {
public:
State(){}
bool operator< (const State& s) const;
bool isGoal();
std::set<State> expand();
};
class UniformCost {
private:
State startState;
std::set<State> closedList; //list of no repeated states
public:
State start;
void setStart(State s);
State* getSolution();
};
void UniformCost::setStart(State st) {
start = st;
}
State* UniformCost::getSolution() {
closedList.insert(start);
while(!closedList.empty()) {
State cur = *closedList.begin();
if(cur.isGoal()) {
return &cur;
}
closedList.erase(cur);
std::set<State> children = cur.expand();
for (std::set<State>::iterator i = children.begin(); i != children.end(); ++i) {
closedList.insert(*i);
}
}
}
My main application creates the initial Node that is a child class of State.
class Node : public State {
public:
std::pair<int,int> loc;
int g_val;
std::set<std::pair<int,int> > dirt;
std::vector<char> path;
bool isGoal() {
return dirt.size() == 0;
}
bool operator< (const State& s) const {
Node n = (Node) s;
if(loc == n.loc) {
return false;
}
if(g_val <= n.g_val) {
return true;
}
return false;
}
std::set<State> expand() {
std::set<State> ret;
return ret;
}
};
How can I override the operator in the Node class that is expecting a "operator< (const State&)"? Or a more general question, how would I handle future "casting" of States?
I have a problem in which I have to return the name of a winner in a fight between two fighters.
The class for fighter is as follows:
class Fighter
{
private:
std::string name;
int health;
int damagePerAttack;
public:
Fighter(std::string name, int health, int damagePerAttack)
{
this->name = name;
this->health = health;
this->damagePerAttack = damagePerAttack;
}
~Fighter() { };
std::string getName()
{
return name;
}
int getHealth()
{
return health;
}
int getDamagePerAttack()
{
return damagePerAttack;
}
void setHealth(int value)
{
health = value;
}
};
I wrote a function that should return the name of the winner.
std::string declareWinner(Fighter* fighter1, Fighter* fighter2,
std::string firstAttacker)
{
// Your code goes here. Have fun!
if(firstAttacker==fighter1->getName())
{
while(fighter1->getHealth()!=0&&fighter2->getHealth()!=0)
{
fighter2->setHealth(fighter2->getHealth()-fighter1->getDamagePerAttack());
if(fighter2->getHealth()<=0)
{
return fighter1->getName();
}
fighter1->setHealth(fighter1->getHealth()-fighter2->getDamagePerAttack());
if(fighter1->getHealth()<=0)
{
return fighter2->getName();
}
}
}
else if(firstAttacker==fighter2->getName())
{
while(fighter1->getHealth()!=0&&fighter2->getHealth()!=0)
{
fighter1->setHealth(fighter1->getHealth()-fighter2->getDamagePerAttack());
if(fighter1->getHealth()<=0)
{
return fighter2->getName();
}
fighter2->setHealth(fighter2->getHealth()-fighter1->getDamagePerAttack());
if(fighter2->getHealth()<=0)
{
return fighter1->getName();
}
}
}
}
This satisfies all my needs, but it throws SIGILL signal, and i do not know what i did wrong. How should I deal with it?
In some conditions, it is possible that function runs to the end and exits without returning a value, that corrupts stack and can lead to SIGILL. As a safe measure you can, for example, add return statement to the end of function.
std::string declareWinner(Fighter* fighter1, Fighter* fighter2,
std::string firstAttacker)
{
// Your code goes here. Have fun!
if(firstAttacker==fighter1->getName())
{
while(fighter1->getHealth()!=0&&fighter2->getHealth()!=0)
{
fighter2->setHealth(fighter2->getHealth()-fighter1->getDamagePerAttack());
if(fighter2->getHealth()<=0)
{
return fighter1->getName();
}
fighter1->setHealth(fighter1->getHealth()-fighter2->getDamagePerAttack());
if(fighter1->getHealth()<=0)
{
return fighter2->getName();
}
}
}
else if(firstAttacker==fighter2->getName())
{
while(fighter1->getHealth()!=0&&fighter2->getHealth()!=0)
{
fighter1->setHealth(fighter1->getHealth()-fighter2->getDamagePerAttack());
if(fighter1->getHealth()<=0)
{
return fighter2->getName();
}
fighter2->setHealth(fighter2->getHealth()-fighter1->getDamagePerAttack());
if(fighter2->getHealth()<=0)
{
return fighter1->getName();
}
}
}
return "No winner"; <= Add before exiting function
}
I also noticed there's a redundancy and possible logical errors in code.
I would rewrite it like this (without changing function signature):
std::string declareWinner(Fighter* fighter1, Fighter* fighter2,
std::string firstAttacker)
{
Fighter *first;
Fighter *second;
if(firstAttacker == fighter1->getName()) {
first = fighter2;
second = fighter1;
} else if (firstAttacker == fighter2->getName()) {
first = fighter1;
second = fighter2;
} else {
// Bad call parameters
return "Bad call"; // Throw exception maybe?
}
// Simulating fighting
do {
std::swap(second,first);
second->setHealth(second->getHealth() - first->getDamagePerAttack());
} while (second->getHealth() > 0);
return first->getName();
}
Hi guys I did not know how to title this properly. The query I have is with the implementation of a stack I made. In the code I would assume we could use this->push() or this->pop() but the scope operator is needed(stack::push).. I do not understand Why?
#include <iostream>
#include <stack>
template <class T >
class SpecialStack : std::stack<T>
{
public:
SpecialStack() : isEmpty(true) {};
void push(T element)
{
if (!isEmpty)
{
T LastMin = min_stack.top();
if (element < LastMin)
{
min_stack.push(element);
}
else
{
min_stack.push(LastMin);
}
}else
{
min_stack.push(element);
}
stack::push(element); // works
//this->push(element); // Unhandled Exception
}
T pop()
{
min_stack.pop();
T out = stack::top();
stack::pop();
return out;
}
T getMin()
{
return min_stack.top();
}
private:
std::stack<T> min_stack;
bool isEmpty;
};
int main()
{
SpecialStack<int> s;
s.push(3);
s.push(2);
s.push(1);
s.push(5);
s.push(6);
//cout << s.getMin() << endl;
s.pop();
s.pop();
s.pop();
std::cout << s.getMin() << std::endl;
system("pause");
}
void push(T element) {
...
this->push(element);
}
The last line calls your push function recursively. Since the process never terminates, you are getting your stack overflow exception.
stack::push is the correct way to tell the compiler you want to call an implementation from the parent class.
I'm developing a LRU-cache in C++, using boost mutexes and locks, in a multi-threaded environment.
The architecture is based on a boost::unordered_map + a lock-free-queue
Insertions work in non-blocking mode (try_lock), but removals should lock the map and proceed.
The problem is that very rarely, the cache-access deadlocks in the removal.
.h
typedef boost::function<std::string ( const std::string &key )> LoaderFunction;
class ListNode;
struct CacheEntry {
CacheEntry(std::string key="", std::string value="");
ListNode * createLruListNode() const;
ListNode * getLruListNode() const;
virtual ~CacheEntry();
const std::string key;
const std::string value;
private:
ListNode ** listNodePP;
};
struct ListNode {
ListNode(const CacheEntry* entry = NULL);
~ListNode();
void setCacheEntry(const CacheEntry* entry);
const CacheEntry * getCacheEntry();
void setDirty();
private:
const CacheEntry * cacheEntry;
bool dirty;
};
typedef LockFreeQueue<ListNode*> List;
typedef boost::unordered_map
< const string , const CacheEntry * >
Cache;
typedef Cache::iterator CacheIter;
.cpp
#include "LockFreeQueue.h"
#include <unistd.h>
using namespace std;
/* ... */
ListNode::ListNode(const CacheEntry* e2) : cacheEntry(e2) {
dirty=false;
}
void ListNode::setCacheEntry(const CacheEntry* entry) {
cacheEntry=entry;
}
const CacheEntry* ListNode::getCacheEntry() {
if(dirty) {
return NULL;
}
return cacheEntry;
}
void ListNode::setDirty() {
dirty=true;
}
std::string PeachCachePartition::get(const string key) {
CacheIter iter=cache->find(key);
string value;
if(iter!=cache->end()) {
__sync_fetch_and_add(_hits,1);
const CacheEntry* entry=iter->second;
value=(entry->value);
lruList->enqueue(entry->getLruListNode());
if(size() > max) { // removes some
int howMany = (int) ceil((*_misses)/(*_hits))+1;
int k=0;
ListNode removedListNode=ListNode();
ListNode * p=&removedListNode;
ListNode ** pp=&p;
while(size() > max && k<howMany) {
if(lruList->dequeue(pp)) {
const CacheEntry * toBeRemoved=p->getCacheEntry();
if(toBeRemoved) {
remove(toBeRemoved->key);
k++;
}
}
}
}
} else {
__sync_fetch_and_add(_misses,1);
value=loader(key);
if(value.size()>0) {
put(key,value);
}
}
return value;
}
void PeachCachePartition::remove(const std::string &key) {
try {
boost::lock_guard<boost::mutex> mapLockGuard(mapMutex);
CacheIter iter = cache->find(key);
if(iter!=cache->end()) {
const CacheEntry * toBeRemoved=iter->second;
if(toBeRemoved->getLruListNode()) {
toBeRemoved->getLruListNode()->setDirty();
}
delete(toBeRemoved);
cache->erase(iter);
__sync_sub_and_fetch(_size,1);
}
} catch (std::exception &e) {
Logger::err(e.what());
}
}
void PeachCachePartition::put(const std::string &key, std::string &value) {
try {
boost::unique_lock<boost::mutex> mapLockGuard(mapMutex,boost::try_to_lock);
if(mapLockGuard.owns_lock()) {
CacheIter iter=cache->find(key);
const CacheEntry * entry;
if(iter!=cache->end()) {
entry=iter->second;
entry->getLruListNode()->setDirty();
} else {
entry = new CacheEntry(key,value);
__sync_add_and_fetch(_size,1);
(*cache)[key] = entry;
}
entry->createLruListNode()->setCacheEntry(entry);
lruList->enqueue(entry->getLruListNode());
}
} catch (std::exception &e) {
Logger::err(e.what());
}
}
Can you explain me what's wrong? I'm almost sure it deadlocks in the removal as it is the only lock it must acquire.
Thanks everybody
edit: I'm using this cache in an apache module which runs mpm_prefork_module: could this be the problem? Should I use boost::interprocess instead of boost::thread?