Implementing Queue With Two Stacks - Dequeuing Test Issue? - c++

I'm trying to implement a queue with two stacks for purposes of understanding both data structures a little better. I have the below, with the main function serving as a test:
#include <iostream>
#include <stack>
using namespace std;
template <class T>
class _Stack : public stack<T> {
public:
T pop(){
T tmp=stack::top();
stack::pop();
return tmp;
}
};
template <class T>
class QueueS {
public:
QueueS(){}
bool isEmpty() const{
return pool.empty();
}
void enqueue(const T& el){
while( !output.empty()) {
input.push(output.pop());
}
input.push(el);
}
T dequeue(){
while(!input.empty()){
output.push(input.pop());
}
return output.pop();
}
T firstElement(){
if(output.empty()) {
return NULL;
}
return output.top();
}
private:
_Stack<T> pool;
_Stack<T> input;
_Stack<T> output;
};
int main(){
QueueS<int> n_QueueS;
//fill the queue of integers 0-9
for(int i=0; i<10;i++)
n_QueueS.enqueue(i);
// add another number to the queue
n_QueueS.enqueue(50);
//retrieve the first element without removing it
cout<<"front of the queue: "<<n_QueueS.firstElement()<<endl;
// removing the first 5 elements from the queue
cout<<"deleting first five elements of the queue: ";
for(int i=0; i<5;i++)
cout<<n_QueueS.dequeue()<<" ";
//removing the remainder of the queue and displaying the result
//should see 5 6 7 8 9 50 - see nothing!
cout<<endl<<"deleting remainder of the queue: ";
while(!n_QueueS.isEmpty())
cout<<n_QueueS.dequeue()<<" ";
if(n_QueueS.isEmpty())
cout<<endl<<"Queue is now empty";
else
cout<<endl<<"Error in emptying the queue";
system("pause");
return 0;
}
It works pretty well thusfar. However, when I run my test, deleting the first five elements works fine, and they display fine. It displays the line "deleting first five elements of the queue:" followed by 0 1 2 3 4, as expected.
However, deleting the second half doesn't display the values after the text "deleting remainder of the queue" like the previous test case did. I'm assuming the problem is minor, but I can't locate it through debugging. Maybe I've overlooked something?
Any help would be greatly appreciated!

First of all, your empty check should be something like this:
bool isEmpty() const{
return input.empty() && output.empty();
}
in enqueue, just push to the input stack:
void enqueue(const T& el){
input.push(el);
}
in enqueue and dequeue, move input to output if output is empty:
T dequeue(){
if (output.empty())
while(!input.empty()){
output.push(input.pop());
}
// throw exception of output.empty() ??
return output.pop();
}
T firstElement(){
if (output.empty())
while(!input.empty()){
output.push(input.pop());
}
if(output.empty()) {
return T(0); // throw exception?
}
return output.top();
}

Related

Copy elements from queue to stack

I want to write a code that copies queue elements in to a stack, and this copied elements should be sorted in the stack.
i've written the code below:
#include <bits/stdc++.h>
using namespace std;
int main(){
int n,x;
queue<int> q;
stack<int> s;
cin >> n;
for(int i=0;i<n;i++){
cin >> x;
q.push(x);
}
while(!q.empty()){
if(s.empty()){
s.push(q.front());
q.pop();
}
else{
if(q.front()>=s.top()){
s.push(q.front());
q.pop();
}
else{
while(q.front()<s.top() && !s.empty()){
q.push(s.top());
s.pop();
}
}
}
}
while(!s.empty()){
cout << s.top() << " ";
s.pop();
}
return 0;
}
but for some test cases like:3 1 2 3,the code does not seem to work.
please help me to figure out the problem with my code.
Your code seems to have a logic error in your inner while loop. You test s.top() before you test for s.empty(), which is the wrong order. s.top() is invalid if s.empty() is true. However, the exercise can be resolved relatively easily as described below.
You can retrieve the underlying container of a container adapter using the following helper:
template <class ADAPTER>
typename ADAPTER::container_type & get_container (ADAPTER &a)
{
struct hack : ADAPTER {
static typename ADAPTER::container_type & get (ADAPTER &a) {
return a.*&hack::c;
}
};
return hack::get(a);
}
Then, after populating the queue, you can copy the contents directly to the stack's underlying container, and sort it.
auto &qc = get_container(q);
auto &sc = get_container(s);
sc.assign(qc.begin(), qc.end());
std::sort(sc.begin(), sc.end());
You have to do what is essentially a selection sort: go through the queue N times, each time selecting the largest element to push onto the stack. The general idea is:
queue = queue containing items
stack = new empty stack
while queue.count > 0
// push the first item from the queue onto the stack
stack.push(queue.pop())
count = queue.count
// for each item remaining in the queue
for (i = 0; i < queue.count; ++i)
// if the item from the queue is larger than what's on the stack,
// then remove the item from the stack and put it back in
// the queue. And put the item from the queue onto the stack.
if (queue.peek() > stack.peek())
queue.push(stack.pop())
stack.push(queue.pop())

algorithm implementation error (DFS)

I was trying to implementing dfs to print paths from starting node . I followed algorithm from Coremen 's book . Here is my code :
DFS
#include<iostream>
#include<stack>
using namespace std;
int vertex,edge,source,time,adjacency_matrix[100][100],parent[100],Distance[100],Finishing_time[100];
string color[100];
stack<int> result;
void inputGraph();
void initialize();
void doDFS();
void doDFSvisit(int);
void printPath();
//void printAll();
//void printAdjacencyMatrix();
//void printColor();
//void printDistance();
//void printParent();
int main(void)
{
inputGraph();
//initialize();
doDFS();
printPath();
//printAll();
return 0;
}
void inputGraph()
{
cout<<"Total vertex : ";
cin>>vertex;
cout<<"Total edge : ";
cin>>edge;
int i,j;
for(i=1; i<=edge; i++)
{
int start,finish;
cout<<"Enter start and end node for edge "<<i<<" : ";
cin>>start;
cin>>finish;
adjacency_matrix[start][finish]=1;
}
cout<<"The adjacency matrix is : "<<endl;
for(i=1; i<=vertex; i++)
{
for(j=1; j<=vertex; j++)
{
cout<<adjacency_matrix[i][j]<<" ";
}
cout<<endl;
}
}
void initialize()
{
cout<<"Enter source node : ";
cin>>source;
}
void doDFS()
{
int i,j;
for(i=1;i<=vertex;i++)
{
color[i]="white";
parent[i]=0;
}
time=0;
for(i=1;i<=vertex;i++)
{
if(color[i]=="white")
{
doDFSvisit(i);
}
}
}
void doDFSvisit(int node)
{
int i;
time=time+1;
Distance[node]=time;
color[node]="grey";
for(i=1;i<=vertex;i++)
{
if(adjacency_matrix[node][i]==1)
{
if(color[i]=="white")
{
parent[i]=node;
doDFSvisit(i);
}
}
}
color[node]="black";
//extra line for result
result.push(node);
//
time=time+1;
Finishing_time[node]=time;
}
void printPath()
{
cout<<"Path :"<<endl;
int i;
for(i=0;i<=result.size();i++)
{
cout<<result.top()<<" -> ";
result.pop();
}
cout<<" End"<<endl;
}
My problem :
for input :
6
6
1 2
1 4
2 3
3 4
5 3
5 6
my output should be :
5 6 1 2 3 4 end
but my output is :
5 6 1 2 end
it seems printing values from stacks creates problem . please correct me where i did mistake , Thanks in advance .
[ P.S. : Pic of the directed graph that I used for input , http://imgur.com/fYsICiQ ]
There is mistake in the print_path function.
Your for-loop termination condition checks result(stack)'s size which decrements each loop-iteration by pop calling.
Your print_path function should look like something like this:
void printPath(){
cout<<"Path :"<<endl;
int i;
while(!result.empty()){
cout << result.top() << " -> ";
result.pop();
}
cout<<" End"<<endl;
}
Additionally consider this DFS implementation:
list<size_t> l[N];
bool used[N];
void DFS(size_t s){
if (used[s])
return;
used[s] = true;
for(auto i = l[s].begin(); i != l[s].end(); i++)
if(!used[*i]){
DFS(*i);
}
}
used is global bool array indicating i'th vertex is visited or not. We have no need to color vertexes. We have to know is it already visited or not.
l is adjacency list (see http://www.geeksforgeeks.org/graph-and-its-representations/ )
We run DFS on some vertex.
If it's visited we do nothing.
Else we mark this vertex as visited. And then go deeper running DFS on each vertex adjacent current vertex.
For more information about DFS see https://en.wikipedia.org/wiki/Depth-first_search
Here's how I would implement DFS in C++. First some observations:
I'll use adjacency lists (std::vectors) rather than an adjacency matrix.
Nodes aren't owned by their neighbors. They're assumed to be owned by a parent Graph object.
So, without further ado:
struct Node {
std::vector<Node *> neighbors;
// Other fields may go here.
}
void process(Node * node)
{
// Actual logic for processing a single node.
}
// Of course, in idiomatic C++, this would be a template
// parameterized by a function object, rather than contain
// a hard-coded call to a fixed `process` function.
void depth_first(Node * start)
{
std::stack <Node *> pending = { start };
std::unordered_set<Node *> visited;
while (!pending.empty()) {
Node * current = pending.pop();
process(current);
for (Node * neighbor : current->neighbors)
if (visited.find(neighbor) == visited.end()) {
pending.push (neighbor);
visited.insert(neighbor);
}
}
}
A nice thing about this implementation is that, in order to get BFS, you only need to replace std::stack with std::queue, and leave the rest of the code exactly as is.

The same expression but different result

So I am doing a question in leetcode. It is Implement Stack using Queues.
If I submit this code below. It is accepted.
class Stack {
public:
queue<int> que;
// Push element x onto stack.
void push(int x) {
que.push(x);
for(int i=0;i<que.size()-1;i++){
que.push(que.front());
que.pop();
}
}
// Removes the element on top of the stack.
void pop() {
que.pop();
}
// Get the top element.
int top() {
return que.front();
}
// Return whether the stack is empty.
bool empty() {
return que.empty();
}
};
but if I only change for(int i=0;i<que.size()-1;++i) to for(int i=0;i<=que.size()-2;i++), I got Time limitation exceeded. Last executed input: push(1),empty().Could somebody tell me why??? Thanks
queue::size() returns a size_t which is basically an unsigned number. and a negative unsigned number converts to a huge number.
So queue::size()-1 --> huge number (0xFFFFFFFF)

Different output when set different breakpoints

I just wrote a code to build a Huffman Tree using MinHeap. When testing I want to output its traversal result.
The algorithm is simple, but my code can't get the right answer. It's strange that the output was different when I set different breakpoints. For instance, it depends on if I set a break point in the loop, such as line 165 input_list.insert(*parent);.
The test input was
4 //number of nodes.
1 1 3 5 //weight of each node.
and the output when debugging it with a breakpoint in the loop is
5
10
1
2
1
5
3
that is correct. But when I just run it without debug, it even didn't have any output. Does anyone know how to explain it?
#include <iostream>
#include <vector>
using namespace std;
#define max_size 100
int sum=0;
class huffman_node
{
public:
int weight;
huffman_node* left_child;
huffman_node* right_child;
huffman_node(){}
huffman_node(int w, huffman_node* l, huffman_node* r):
weight(w),left_child(l),right_child(r) {}
};
vector <huffman_node> node_list;
class minheap
{
public:
minheap()
{
heap=new huffman_node [max_size];
current_size=0;
}
~minheap()
{
delete []heap;
}
void siftdown(int start, int m)
{
int i=start;
int j=2*i+1;
huffman_node temp=heap[i];
while(j<=m)
{
if(j<m && heap[j+1].weight<heap[j].weight)
{
++j;
}
if(temp.weight<=heap[j].weight)
{
break;
}
else
{
heap[i]=heap[j];
i=j;
j=2*i+1;
}
}
heap[i]=temp;
}
void siftup(int start)
{
int j=start;
int i=(j-1)/2;
huffman_node temp=heap[j];
while(j>0)
{
if(heap[i].weight<=temp.weight)
{
break;
}
else
{
heap[j]=heap[i];
j=i;
i=(j-1)/2;
}
heap[j]=temp;
}
}
bool insert(const huffman_node& input)
{
if(current_size==max_size)
{
cout<<"minheap full"<<endl;
return false;
}
heap[current_size]=input;
siftup(current_size);
++current_size;
return true;
}
bool remove_min(huffman_node& output)
{
if(!current_size)
{
cout<<"minheap empty"<<endl;
return false;
}
output=heap[0];
heap[0]=heap[current_size-1];
--current_size;
siftdown(0,current_size-1);
return true;
}
private:
huffman_node* heap;
int current_size;
};
void route_length(huffman_node* &root,int depth)
{
if(root!=NULL)
{
// if(root->left_child==NULL&&root->right_child==NULL)
// {
// sum+=depth*root->weight;
// }
route_length(root->left_child,depth+1);
cout<<root->weight<<endl;
route_length(root->right_child,depth+1);
}
else
{
return;
}
}
int main()
{
minheap input_list;
int n;
cin>>n;
for(int i=0;i<n;++i)
{
int key;
cin>>key;
huffman_node input(key,NULL,NULL);
input_list.insert(input);
cin.get();
}
huffman_node* root;
for(int i=0;i<n-1;++i)
{
huffman_node* parent;
huffman_node out1;
huffman_node out2;
input_list.remove_min(out1);
input_list.remove_min(out2);
node_list.push_back(out1);
node_list.push_back(out2);
parent=new huffman_node(out1.weight+out2.weight,&node_list[node_list.size()-2],&node_list[node_list.size()-1]);
input_list.insert(*parent);
root=parent;
}
route_length(root,0);
// cout<<sum<<endl;
return 0;
}
The problem is that you are using pointers to elements of a vector<huffman_node> and storing these in your data structure (i.e. left and right members of the huffman_node object).
The thing that is randomly killing your program is that std::vector moves values around in memory when you append to it. The contents of the elements of the vectors are preserved, but the location is not. Once it moves the elements, the memory where the vector used to be can be overwritten by whatever (i.e. gdb needs heap memory too) and now the pointers are pointing to garbage.
As a quick sanity check, you can make your code not crash by reserving space in your node_list by calling
node_list.reserve(max_size*2);
in the beginning of main. This is not the right way of developing this piece of code further, but should illustrate the problem.
It would be better if your node_list was a vector<huffman_node*> instead. Or if you changed the left/right members to be vector indices instead of pointers.

C++ Priority Queue, logical error, can't figure out

I'm implementing a simple priority queue in C++.
However when it runs, it prints out gibberish numbers.
Am I somehow trying to access invalid entries in the array in my code?
Below is the code.
Also, is my "remove" function somehow not doing its job? Conceptually, shall I be putting null into the first entry and return whatever was just erased?
Thanks.
[Priority.h]
#ifndef Priority_h
#define Priority_h
class Priority
{
public:
Priority(void);
Priority(int s);
~Priority(void);
void insert(long value);
long remove();
long peekMin();
bool isEmpty();
bool isFull();
int maxSize;
long queArray [5];
int nItems;
private:
};
#endif
[Priority.cpp]
#include <iostream>
#include <string>
#include <sstream>
#include <stack>
#include "Priority.h"
using namespace std;
Priority::Priority(void)
{
}
Priority::Priority(int s)
{
nItems = 0;
}
Priority::~Priority(void)
{
}
void Priority::insert(long item)
{
int j;
if(nItems==0) // if no items,
{
queArray[0] = item; nItems++;
}// insert at 0
else // if items,
{
for(j=nItems-1; j=0; j--) // start at end,
{
if( item > queArray[j] ) // if new item larger,
queArray[j+1] = queArray[j]; // shift upward
else // if smaller,
break; // done shifting
} // end for
queArray[j+1] = item; // insert it
nItems++;
} // end else (nItems > 0)
}
long Priority::remove()
{
return queArray[0];
}
long Priority::peekMin()
{
return queArray[nItems-1];
}
bool Priority::isEmpty()
{
return (nItems==0);
}
bool Priority::isFull()
{
return (nItems == maxSize);
}
int main ()
{
Priority thePQ;
thePQ.insert(30);
thePQ.insert(50);
thePQ.insert(10);
thePQ.insert(40);
thePQ.insert(20);
while( !thePQ.isEmpty() )
{
long item = thePQ.remove();
cout << item << " "; // 10, 20, 30, 40, 50
} // end while
cout << "" << endl;
system("pause");
}
Here is one error:
for(j=nItems-1; j=0; j--) // start at end,
^ this is assignment, not comparison.
I am also not convinced that there isn't an off-by-one error in
queArray[j+1] = item; // insert it
Finally, your default constructor fails to initialize nItems.
There could be further errors, but I'll stop at this.
I agree with the other answers here, but I would add this:
Your "Remove" method isn't actually removing anything - it is just returning the first element - but it doesn't do anything to the array itself.
Edited to say that your insert method needs some work - it may or may not write over the end of the array, but it is certainly confusing as to what it is doing.
Try initializing your queue array in the constructor.