Compare a Queue and a Stack's content - c++

Suppose we have in c++, using STL Stack and Queue
Stack: [1 2 3 4 5] <=>
Queue: => [5 4 3 2 1] =>
What is the most elegant way to recursively check that the data entries are the same in terms of content and order? Say the stack and queue shown above have the same data and same order.
I'm having a problem conceptually understanding what to do because the data pop() in opposite order.

A partially recursive solution would be to recursively pop all the elements from the queue in an auxiliary stack and then check if the auxiliary stack and the original stack are the same. This check can be done also recursively.

No need for recursion, this would be a useless waste of resources. No need to mutate your queue and stack either (in other words, this works even on const's).
Assuming your std::stack and std::queue both internally use the same type of underlying container (which should be std::dequeue if you used the default) then you can access the protected members c (your real containers) of both queue and stack and compare them using operator ==:
#include <iostream>
#include <queue>
#include <stack>
template<typename Adapter>
typename Adapter::container_type const& getContainer(const Adapter& adapter) {
struct AccessProtected : private Adapter {
static typename Adapter::container_type const& getContainer(const Adapter& adapter) { return adapter.*&AccessProtected::c; }
};
return AccessProtected::getContainer(adapter);
}
int main() {
std::queue<int> queue;
std::stack<int> stack;
for (int i = 0; i < 10; ++i) {
queue.push(i);
stack.push(i);
}
std::cout << (getContainer(queue) == getContainer(stack) ? "equal" : "not equal") << std::endl;
return 0;
}
Now, if you use different containers types as the underlying implementation of queue and stack, you can still use that same getContainer() technique to obtain containers that are sorted in the same order: both queue::push() and stack::push() call the underlying container's push_back() method, it's only when you pop() (and similar operations) that the reversing happens for stack. Since those underlying containers will be in the same order, you can then compare things more easily (left as an exercise to the reader ;)).
Credit: I was too lazy to reimplement a protected member accessor again, so I shamelessly copied and modified this one.

If by recursion, you do not mean a recursive function call, but just looping, then here's an answer. The function first checks if the stack and queue are the same size. If they aren't the same size, the function returns false. The function has a local stack object that gets the stack parameter's elements, in order to be popped in the reverse order as the stack parameter that is passed in. Then a loop checks each front/top element of stack and queue for equality. If equal, the loop continues to the next iteration. If not equal, the function returns false. If the loop finishes without returning false, the function returns true.
#include <iostream>
#include <stack>
#include <queue>
using namespace std;
bool check(stack<int> stackPar, queue<int> queuePar)
{
if (stackPar.size() != queuePar.size())
{
return false;
}
stack<int> reverseStack;
for (int i = 0, initialSize = stackPar.size(); i < initialSize; ++i)
{
reverseStack.push(stackPar.top());
stackPar.pop();
}
for (int i = 0; i < reverseStack.size(); ++i)
{
if (reverseStack.top() == queuePar.front())
{
reverseStack.pop();
queuePar.pop();
}
else
{
return false;
}
}
return true;
}
int main()
{
stack<int> myStack;
queue<int> myQueue;
for(int i = 1; i <= 5; ++i)
{
myStack.push(i);
myQueue.push(i);
}
cout << "Stack and queue are ";
cout << ( check(myStack, myQueue) ? "equal." : "not equal." ) << endl;
return 0;
}

U may not pop them simultaneously, u can try to pop one(use something record it) ADT(dont pop queue, pop stack), and to the base(size==1), and u compare and made some change to the queue, and returns. Then do something with the recorder and the currently queue's front after every recursion calls, you will find the answer.

Related

Multiple threads add elements concurrently on different vectors of the same vector occurs error

#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
struct A {
std::vector<int> a;
};
struct B{
std::vector<A> b;
std::mutex mtx;
};
void work(int id, struct B& b) {
std::unique_lock<std::mutex> lck(b.mtx);
b.b.push_back(A());
struct A& a = b.b.back();
lck.unlock();
for(int i = 0; i < 1000; i++) {
std::cout << id << " " << i << std::endl;
a.a.push_back(i);
}
}
int main() {
struct B b;
std::thread t1, t2;
t1 = std::thread([&] {
work(1, b);
});
t2 = std::thread([&] {
work(2, b);
});
t1.join();
t2.join();
return 0;
}
This code occurs some errors (like segmentation fault)
As I wrote above, struct B has a vector of struct A and struct A has a vector of int.
Step 1) Each threads pushes new struct A element to the same vector (b.b) with critical section.
Step 2) After then, each thread pushes new int element to the vector a of struct A each created without critical section.
I thought pushing new element to the same vector concurrently should occurs some problems, but pushing new element to the different vectors concurrently should not occur errors.
If I put whole work function into the critical section, it doesn't occur error.
So, I concluded pushing new element to the different vectors will not occur error, BUT if they are in the same vector, it occurs error.
But I cannot explain the reason. Someone please tell me about this. :(
When the second thread pushes a new value to b.b this vector might get resized. If it gets resized all references to it's elements are getting invalidated. So the reference A& a of the first thread gets invalidated.
You could
use a std::list (linked list)
resize() the vector b.b before working with it, so it doesn't need to be resized later (or reserve(), doesn't make much of a difference here)
std::vector reallocates its memory when you push_back, because it needs additional memory.
If you reserve() the vector, it won't reallocate until it needs additional memory.

Implementation of stack using vectors in c++

#include<iostream>
#include<vector>
using namespace std;
class Stack {
private:
int maxSize;
vector<int> v;
int top;
public:
Stack(int size) {
this->maxSize = size;
this->v.reserve(this->maxSize);
this->top = -1;
}
void push(int j) {
if (!(this->isFull())) {
this->v[++this->top] = j;
} else {
cout << "stack is full"<<endl;
}
}
int pop() {
if (!(this->isEmpty())) {
return this->v[this->top--];
} else {
cout << "\nstack is empty"<<endl;
cout<< "StackOverflow "<<endl;
}
}
int peak() {
return this->v[this->top];
}
bool isEmpty() {
return (this->top == -1);
}
bool isFull() {
return (this->top == this->maxSize - 1);
}
};
int main() {
Stack s(10);
s.push(10);
s.push(20);
cout<<s.pop();
cout<<"\n"<<s.pop();
s.push(40);
cout<<"\n"<<s.pop();
}
How can I make this code more better and reliable for these reasons:
The output of this code is 20 10 40 .
But in the output I want to print "Stack is empty" after every
time the stack is empty after popping out all the elements from the
stack
It fails toprint "Stackis Empty " every time .
You have UB in your code:
this->v[++this->top] = j;
return this->v[this->top--];
ans so on. The fact that you reserved space in a std::vector does not make accessing thous elements legal, you access elements out of bounds. And you overcomplicated your code - std::vector maintains it's size so you do not need index top at all. All you need is push_back() adding element and use back() to access last and then pop_back() to remove it. You can use std::vector>::empty()or std::vector::size() to check if there are elements left.
The specific problem in your code is due to your attempting out of bounds access with a std::vector; the behaviour of which is undefined. Note that reserve does not make that number of elements available for use; only potentially available without a subsequent memory reallocation. If you had used at rather than [] then your C++ standard library would have thrown a runtime error.
std::vector has push_back and a pop_back functions which does allow you to use it to model a stack reasonably effectively.
But, typedef std::stack<int> Stack; in place of all your code is by far the best way.
Don't use C++ standard library container objects to model other containers that are also in the C++ standard library. Container objects are really difficult to write properly; and take a lot of debugging.
The way you programmed it, it only prints "Stack is empty" if the stack is already empty when you call pop, not when it has 1 element and is only empty after calling pop.
Suppose you have 1 element on the stack. So top is 0.
int pop() {
if (!(this->isEmpty())) {
This if evaluatetes to true, and therefore nothing will be printed. This is because isEmpty() evaluates to false with top set to 0.
What you want to do is doing the pop first, and then checking if the stack is empty. On top of checking it at the beginning either way, because you can't pop an empty stack.

How to make pointer/reference on element in vector?

I have two vectors and for some elements (not all) i need them to be connected ~ if i delete/change this element in one vector it should be removed/changed in both.
Something similar like pointers:
int r = 10;
int *p= &r;
*p = 3;
For example in next code it should change myvector2[0].a to 7.
#include <iostream>
#include <vector>
using namespace std;
struct elt {
int a, b, c;
};
int main()
{
vector<elt> myvector;
vector <elt> myvector2;
elt elt1 = {1,3,3};
myvector.push_back(elt1);
elt *elt2 = &elt1;
myvector2.push_back(*elt2);
myvector[0].a=7;
cout << myvector[0].a << endl; //7
cout << myvector2[0].a << endl; //1
return 0;
}
How can i make this possible? Please help!!!
As tgmath explained, the issue is that you wind up with two different objects in your vectors, as the standard containers store elements by value. I would recommend that you use shared pointers to properly maintain the lifetime of the objects (note this uses C++11 features):
#include <iostream>
#include <vector>
#include <memory>
struct elt {
int a, b, c;
};
int main()
{
std::vector<std::shared_ptr<elt>> myvector;
std::vector<std::shared_ptr<elt>> myvector2;
auto elt1 = std::make_shared<elt>(elt {1,3,3});
myvector.push_back(elt1);
myvector2.push_back(elt1);
myvector[0]->a=7;
std::cout << myvector[0]->a << std::endl; //7
std::cout << myvector2[0]->a << std::endl; //7
return 0;
}
Pointers and references (and iterators) to elements of std::vector are invalidated whenever the vector reallocates, which can happen during insertion. So you can only keep these if the vector is guaranteed not to reallocate for the lifetime of the pointer/reference. This can be achieved if you don't insert into the vector, or if you call reserve() on it before you start (and before you acquire the pointer/reference/iterator), extending its capacity so that no reallocations will be necessary.
If you can't guarantee that, your only option is to keep the index instead of a pointer/reference. Of course, you will also need access to the vector itself for this to work, but you should be able to keep a pointer or reference to it, e.g.
typedef std::pair<std::vector<elt>*, size_t> ReferenceIntoVector;
myvector2.push_back(*elt2); adds a copy of *elt2 into myvector2
This means that both vector have their own copy of the elt object. And both of them are distinct from elt1.
If you change the one in the first vector, the second does not change at all.
For this purpose yiu would need a std::vector<elt*> to have different pointers to the same object in different vectors.
First, there is no built in way to automatically remove an element from one vector if you happen to delete it from another.
In my opinion there are two different challenges here:
How can I update an element pointed to by one list to be updated in another?
How can I remove an element from one list, and have that removed from the other?
The first question is already answered in the other posts: Use std::shared pointers instead of your native pointers. They are just as fast and will take care of all the memory management for you.
Please note: That this approach will only work as long as you are only changing the value of the element pointed to by the shared pointer, and not what the shared pointer is pointing to.
In other words/code:
std::vector<std::shared_ptr<elt>> vec1, vec2;
// Insert some elements
vec1.push_back( std::make_shared( elt{ 1, 2, 3} );
vec2.push_back( vec1.back() );
vec1[0]->x = 5; // OK, updated in both vectors.
vec1[0] = make_shared(elt {3,2,1}); // Error: vec1[0] is pointing to a new object.
The other challenge is much harder, how can you automatically delete an element from both vectors. The short answer is "You can't", the slightly longer is, you can but not directly.
Approach 1: Setting deleted elements to nullptr.
This approach is a bit dirty an not something I would recommend as it requires all code that use either vector to check whether an element is nullptr.
// Encapsulate the object inside a `std::unique_ptr`
std::vector< std::shared_ptr< std::unique_ptr< elt >>> vec1, vec2;
// Adding elements are done similarly as before
vec1.push_back( std::make_shared( std::make_unique( elt{ 1, 2, 3} )));
vec2.push_back( vec1.back() );
// Now to delete a element you would do as follows
vec1[0]->reset(nullptr); // Flag this element as deleted
vec1[0]->erase( vec1.begin() ); // Remove element from vec1
// Now let us assume we are iterating through the other vector at a later time:
for (auto it = vec2.begin(); it != vec2.end(); ++it ) { // Using iterators makes the code cleaner.
if ( **it == nullptr ) { // If the unique_ptr == nullptr
it = erase(it);
else {
etl & the_value = ***it; // Yes you need all three, one for the iterator, one for the shared_ptr and one for the unique_ptr...
}
}
As you can see this quickly gets hairy. But if that is all you need it can work.
Approach 2: (The better in my opinion) Is to use the Observer/Observed Design Pattern.
In order to implement this pattern you will need to exchange your vector for another class. Let us make a simple example:
// First, create an interface describing all operations you want to be
// informed about.
template<class T>
class SharedElementListObserver {
protected:
void elementDeleted( const shared_ptr<T> & elem ) = 0;
}
template<class T>
class SharedElementList : public SharedElementListObserver<T> {
std::vector<std::shared_ptr<T>> data;
std::unordered_set<SharedElementListObserver*> observers;
public:
void push_back( const T & elem ) { data.push_back( std::make_shared<T>( elem )); }
void push_back( std::shared_ptr &sptr ) { data.push_back( sptr ); }
shared_ptr<T> operator[] (int index) {
return data[index];
}
shared_ptr<const T> operator[] (int index ) const {
return std::static_pointer_cast<const T>( data[index] );
}
// This will cause all instances of elem in all lists
// linked either directly and indirectly to this
// to be removed.
void delete( int idx ) {
if (idx >= 0 && idx < data.size() ) {
shared_ptr<T> temp = data[idx];
data.erase( data.begin() + idx );
for (auto observer : observers) {
observer->elementDeleted(temp);
}
}
}
// Link another list to this one to listen to deletions.
void link( SharedElementListObserver* observer ) {
if (observer == this) return;
else if (observers.insert(observer).second) {
observer->observers.insert(this);
}
}
// Unlink previously linked observer.
void unlink(SharedElementListObserver* observer) {
observer->observers.erase(this);
this->observers.erase(observer);
}
protected:
void elementDeleted( shared_ptr<T> & elem ) {
for (int i = 0; i < data.size(); ) {
if (data[i] == elem)
delete(i); // Not infinite loop, because of test above.
else
i++;
}
}
// You also need to write an operator=, a copy-constructor and a destructor
// that ensures that there are no dead observers in the observers list.
};
Depending on your assumptions this class can be implemented in a number of different ways. Some probably simpler than what I just did.
Please let me know if there are any errors in the above code.

What parameter should my pop function take?

Here's my function,
template <class KeyType >
KeyType * Stack<KeyType>::Pop(KeyType& x) {
if (IsEmpty()) { //isempty is just a bool function
StackEmpty(); //just prints out that stack is empty
return 0; //bad coding breaking out of the function
}
x = stack[top--]; //stack is a pointer to an array, top is the top of the stack
return &x;
}
My questions is:
I'm not sure how this would be called in main. To my understanding a pop function shouldn't really have an option of what to pop off of the stack. LIFO right? The main question is what exactly does the Keytype& x parameters take and how would you call it in main? (in this case the KeyType is initialized as KeyType *stack an int in this particular program).
That's a very weirdly designed function.
Stack is a class template parameterised by the type stored on the stack (named KeyType for some reason). The function takes an output parameter x of type reference to KeyType and if the stack is not empty, assigns the popped value into x. At the same time, it returns its address (it returns a pointer to KeyType). If the stack was empty when pop() was called, it will call StackEmpty() and then return a null pointer.
Usage:
int main() {
Stack<int> stack;
//fill stack somehow
int val;
stack.pop(val); //val will be set to the popped item, or unchanged if the stack was empty
// You can also use the return value to access the popped item:
std::cout << *stack.pop(val);
// ... or use it to test whether the pop() succeeeded
if (stack.pop(val)) {
//val was popped, use it
}
}
It fills the value of the popped item
int main(..)
{
...
int poppedItem;
stack.pop(poppedItem);
}
If the KeyType parameter is an int as you said, then your Stack will probably look like this:
Stack<int> stack;
The ampersand in the Pop method means that you pass in a reference of the KeyType (which is int in your case). That is, the Pop method does not only return the value of the popped item but also puts the value in the passed argument.
int a, b;
a = *(stack.pop(b));
cout << a << " = " << b << endl;
variable x is the same that return value (just other way to get top element that was excluded from stack)
Stack<int> my_stack;
// blah-blah-blah ...
int tmp;
int* tmp_pointer = my_stack.pop(tmp);
some_func(tmp);
some_other_func(*tmp_pointer);
// tmp_pointer == &tmp;
// you can use one of two ways
To my understanding the function takes any element of keytype and retrieves a reference.
so calling
int value = 0;
Pop(value);
is calling Pop with &value - so in fact with the address of the int value and therefore by reference.
I wonder about the return 0 in case you called Pop with any non numerical datatype the compiler might tell you, that the return statement is invalid. Maybe returning NULL would be better. (At least better to read)

Queue with unique entries in c++

I need to implement a queue containing unique entries(no duplicates) in C or C++. I am thinking of maintaining a reference of elements already available in queue but that seems very inefficient.
Kindly let me know your suggestions to tackle this.
How about an auxiliary data structure to track uniqueness:
std::queue<Foo> q;
std::set<std::reference_wrapper<Foo>> s;
// to add:
void add(Foo const & x)
{
if (s.find(x) == s.end())
{
q.push_back(x);
s.insert(std::ref(q.back())); // or "s.emplace(q.back());"
}
}
Or, alternatively, reverse the roles of the queue and the set:
std::set<Foo> s;
std::queue<std::reference_wrapper<Foo>> q;
void add(Foo const & x)
{
auto p = s.insert(x); // std::pair<std::set<Foo>::iterator, bool>
if (s.second)
{
q.push_back(std::ref(*s.first)); // or "q.emplace_back(*s.first);"
}
}
queuing:
use std::set to maintain your set of unique elements
add any element that you were able to add to the std::set to the std::queue
dequeueing:
remove element from std::queue and std::set
std::queue is a container adaptor and uses relatively few members of the underlying Container. You can easily implement a custom container that contains both: an unordered_map of reference_wrapper<T> and a deque<T>. It needs at least members front and push_back. Check inside that hash_map when push_back of your container is called and reject accordingly (possibly throw). To give the complete example:
#include <iostream>
#include <set>
#include <deque>
#include <queue>
#include <unordered_set>
#include <functional>
namespace std {
// partial specialization for reference_wrapper
// is this really necessary?
template<typename T>
class hash<std::reference_wrapper<T>> {
public:
std::size_t operator()(std::reference_wrapper<T> x) const
{ return std::hash<T>()(x.get()); }
};
}
template <typename T>
class my_container {
// important: this really needs to be a deque and only front
// insertion/deletion is allowed to not get dangling references
typedef std::deque<T> storage;
typedef std::reference_wrapper<const T> c_ref_w;
typedef std::reference_wrapper<T> ref_w;
public:
typedef typename storage::value_type value_type;
typedef typename storage::reference reference;
typedef typename storage::const_reference const_reference;
typedef typename storage::size_type size_type;
// no move semantics
void push_back(const T& t) {
auto it = lookup_.find(std::cref(t));
if(it != end(lookup_)) {
// is already inserted report error
return;
}
store_.push_back(t);
// this is important to not have dangling references
lookup_.insert(store_.back());
}
// trivial functions
bool empty() const { return store_.empty(); }
const T& front() const { return store_.front(); }
T& front() { return store_.front(); }
void pop_front() { lookup_.erase(store_.front()); store_.pop_front(); }
private:
// look-up mechanism
std::unordered_set<c_ref_w> lookup_;
// underlying storage
storage store_;
};
int main()
{
// reference wrapper for int ends up being silly
// but good for larger objects
std::queue<int, my_container<int>> q;
q.push(2);
q.push(3);
q.push(2);
q.push(4);
while(!q.empty()) {
std::cout << q.front() << std::endl;
q.pop();
}
return 0;
}
EDIT: You will want to make my_container a proper model of container (maybe also allocators), but this is another full question. Thanks to Christian Rau for pointing out bugs.
There is one very important point you've not mentioned in your question, and that is whether your queue of items is sorted or have some kind of ordering (called a Priority queue), or unsorted (called a plain FIFO). The solution you choose will depend only on the answer to this question.
If your queue is unsorted, then maintaining an extra data structure in addition to your queue will be more efficient. Using a second structure which is ordered in some way to maintain the contents of your queue will allow you check if an item already exists in your queue or not much quicker that scanning the queue itself. Adding to the end of an unsorted queue takes constant time and can be done very efficiently.
If your queue must be sorted, then placing the item into the queue requires you to know the item's position in the queue, which requires the queue to be scanned anyway. Once you know an item's position, you know if the item is a duplicate because if it's a duplicate then an item will already exist at that position in the queue. In this case, all work can be performed optimally on the queue itself and maintaining any secondary data structure is unnecessary.
The choice of data structures is up to you. However, for (1) the secondary data structure should not be any kind of list or array, otherwise it will be no more efficient to scan your secondary index as to scan the original queue itself.