Implement a stack
#include <iostream>
#include <stdexcept>
using namespace std;
template<typename T>
class ListNode{
public:
int val;
ListNode<T>* pre;
ListNode<T>(int val):val(val),pre(NULL){}
};
template<typename T>
class stack{
private:
ListNode<T>* list;
int Lsize;
public:
stack();
~stack();
T top();
void pop();
void push(T &element);
int size();
};
template<typename T>
stack<T>::stack(){
list=NULL;
Lsize=0;
}
template<typename T>
stack<T>::~stack<T>(){}
template<typename T>
T stack<T>::top(){
if(list==NULL)throw range_error("The stack is empty.");
return list->val;
}
template<typename T>
void stack<T>::pop(){
if(list==NULL)throw range_error("The stack is empty.");
list=list->pre;
Lsize--;
}
template<typename T>
void stack<T>::push(T &element){
if(element==NULL) throw invalid_argument("The element is NULL.");
ListNode<T> *node = new ListNode<T>(element);
node->pre = list;
list=node;
Lsize++;
// return *this;
}
template<typename T>
int stack<T>::size(){
return Lsize;
}
3.1 Describe how you could use a single array to implement three stacks
first idea: divide a array to three parts([0,n/3), [n/3,2n/3), [2n/3,n)), each part store a stack.
second idea: build a struct that store the val and the preindex of the top element, then use a array to store these three stack structure.
3.2 How would you design a stack which, in addition to push and pop, also has a function min which returns the minimum element? Push, pop and min should all operate in O(1) time
the above of stack's pop and push are O(1), so the important part is implementing a min operate. We add a linked list to store current's min element, named minList.
class stack{
ListNode<T> *list;
ListNode<T> *minList;
int Lsize;
public:
stack();~stack();void pop();void push(T &element); T miniMum();
}
template<typename T> //following we ignore, but codes needs.
void stack<T>::push(){
ListNode<T> *node1 = new ListNode<T>(element);
node1->pre = list;list=node1;
ListNode<T> *node2 = new ListNode<T>(element);
node2->pre=minList;minList=node2;
if(minList->pre&&minList->pre->val<minList->val)minList->val = minList->pre->val;
++Lsize;
}
void stack<T>::pop(){
if(Lsize<=0)return;
list=list->pre;minList=minList->pre;
}
T stack<T>::miniMun(){
return minList->val;
}
3.3 Imagine a (literal) stack of plates If the stack gets too high, it might topple There- fore, in real life, we would likely start a new stack when the previous stack exceeds some threshold Implement a data structure SetOfStacks that mimics this SetOf- Stacks should be composed of several stacks, and should create a new stack once the previous one exceeds capacity SetOfStacks push() and SetOfStacks pop() should behave identically to a single stack (that is, pop() should return the same values as it would if there were just a single stack)
FOLLOW UP
Implement a function popAt(int index) which performs a pop operation on a specific sub-stack
we build a vector<ListNode*> to store all stacks, a variable curIndex to represent our operation position at current time, and other vector<int> to store the length of all stacks. When we pop(), we first look the length of curIndex, if the length >0,then pop this curIndex, if the length==0,then come to curIndex-1, if this length ==0, then come to next. When we push(), we first look the length of curIndex also, if the length< MAXCAPACITY, push. Else build a new ListNode* and push. When we popAt(int index), we pop at vector[index].
class SetOfStacks{
vector<ListNode<T>*> vecList;
vector<int> listSize;
int curIndex;
public:
SetOfStacks();~SetOfStacks();void pop();void push(T &element);void popAt(int index);
};
SetOfStacks<T>::SetOfStacks(){
vecList.push_back(NULL);
listSize.push_back(0);
curIndex=0;
}
void SetOfStacks<T>::pop(){
while(listSize[curIndex]==0){
curIndex--;
if(curIndex>0){listSize.pop_back(); vecList.pop_back();}
if(curIndex<0)return;
}
vecList[curIndex]=vecList[curIndex]->pre;
listSize[curIndex]--;
}
void SetOfStacks<T>::push(T &element){
if(element==NULL)throw invalid_argument("");
ListNode<T> *node = new ListNode<T>(element);
if(listSize[curIndex]>=MAXCAPACITY){
vecList.push_back(NULL);listSize.push_back(0);curIndex++;
}
node->pre = vecList[curIndex];
vecList[curIndex]=node;
listSize[curIndex]++;
}
void SetOfStacks<T>::popAt(int index){
if(vecList.size()-1<index||listSize[index]<=0)return;
vecList[index]=vecList[index]->pre;
listSize[index]--;
}
3.4 In the classic problem of the Towers of Hanoi, you have 3 rods and N disks of different sizeswhichcanslideontoanytower Thepuzzlestartswithdiskssortedinascending order of size from top to bottom (e g , each disk sits on top of an even larger one) You have the following constraints:
(A) Only one disk can be moved at a time
(B) A disk is slid off the top of one rod onto the next rod
(C) A disk can only be placed on top of a larger disk
Write a program to move the disks from the first rod to the last using Stacks
classic hanoi problem. recursion problem. following a briefly skeleton code:
class Tower{
stack<T> stDisk;
public:
moveTopTo(Tower t){
T top = stDisk.top();stDisk.pop();
t.push(top);
}
moveDisk(int n,Tower dest,Tower buff){
if(n>0){
moveDisk(n-1,buff,dest);
moveTopTo(dest);
buff.moveDisk(n-1,dest,this);
}
}
};
int main(){
stDisk[0].moveDisk(n,stDisk[2],stDisk[1]);
}
3.5 Implement a MyQueue class which implements a queue using two stacks.
Declare two stacks: pushSt and popSt, pushSt is used to push element, and popSt is used to pop element. When popSt is empty, pop() pushSt and push its top() to popSt one by one. Then pop() and top() popSt.
template<typename T>
class MyQueue{
stack<T> pushSt;
stack<T> popSt;
int size;
public:
MyQueue();
~MyQueue();
T top();
void pop();
void push(T &element);
};
template<typename T>
MyQueue<T>::MyQueue(){size=0;}
template<typename T>
MyQueue<T>::~MyQueue<T>(){}
template<typename T>
T MyQueue<T>::top(){
if(size==0){throw range_error("The queue is empty.");}
if(popSt.empty()){
while(!pushSt.empty()){
T temp = pushSt.top();pushSt.pop();
popSt.push(temp);
}
return popSt.top();
}
return popSt.top();
}
template<typename T>
void MyQueue<T>::pop(){
if(pushSt.empty()&&popSt.empty()){throw range_error("The queue is empty.");}
if(popSt.empty()){
while(!pushSt.empty()){
T temp = pushSt.top();pushSt.pop();
popSt.push(temp);
}
popSt.pop();
}
popSt.pop();
size--;
}
template<typename T>
void MyQueue<T>::push(T &element){
if(element==NULL)throw invalid_argument("The element is NULL.");
pushSt.push(element);
size++;
}
3.6 Write a program to sort a stack in ascending order You should not make any assumptions about how the stack is implemented The following are the only functions that should be used to write this program: push | pop | peek | isEmpty
we declare one more stack: st, the original stack is s. Using these two stack, we can make by insert element from s to st one by one and promising st is in ascending order.
stack<T> ascendStack(stack<T> s){
stack<T> st;
while(!s.isEmpty()){
T temp = s.peek();s.pop();
while(!st.isEmpty()&&st.peek()>temp){
s.push(st.peek());st.pop();
}
st.push(temp);
}
return st;
}