[Cracking the Coding Interview] Chapter 3 - Stacks and Queues

本文探讨了栈在多种场景下的应用及其实现方法,包括使用单数组实现三个栈、设计带有min功能的栈、模仿多栈行为的数据结构、解决汉诺塔问题、利用两个栈实现队列以及栈排序算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

3.1 Describe how you could use a single array to implement three stacks.

/* solution for question 3.1 */ template<class T> class TriStack{ private: T *data; int size; int begin[3], end[3]; public: /* constructor */ TriStack(int maxSize = 100){ maxSize = maxSize < 10 ? 100 : maxSize; data = new T[maxSize]; begin[0] = end[0] = 0; begin[1] = end[1] = maxSize / 3; begin[2] = end[2] = maxSize / 3 * 2; size = maxSize; } /* destructor */ ~TriStack(){ if(data != NULL){ delete[] data; } } /* push */ void push(T &x, int stackId){ if(stackId < 0 || stackId > 2){ cerr << "Invalid stack id!" << endl; return; } // push if( (stackId < 2 && end[stackId] < begin[stackId+1]) || (stackId == 2 && end[stackId] < size) ){ data[end[stackId]++] = x; } else{ cerr << "Out of stack!" << endl; } } /* pop */ void pop(int stackId){ if(stackId < 0 || stackId > 2){ cerr << "Invalid stack id!" << endl; return; } // pop if(end[stackId] > begin[stackId]){ end[stackId]--; } else{ cerr << "Empty stack!" << endl; } } /* top */ T top(int stackId){ if(stackId < 0 || stackId > 2){ cerr << "Invalid stack id!" << endl; return T(NULL); } // pop if(end[stackId] > begin[stackId]){ return data[end[stackId]-1]; } else{ cerr << "Empty stack!" << endl; return T(NULL); } } /* output */ void output(){ for(int i = 0; i < size; ++i){ cout << data[i] << " "; } cout << endl; } };


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.

/* solution for question 3.2 */ template <class T> class MinStack{ private: stack<T> data; stack<T> minData; public: /* constructor */ MinStack(){} /* push */ void push(T &x){ if(data.empty()){ minData.push(x); } else{ minData.push( minData.top() < x ? minData.top() : x ); } data.push(x); } /* pop */ void pop(){ data.pop(); minData.pop(); } /* top */ T top(){ if(data.empty()){ cerr << "Empty stack!" << endl; return T(NULL); } else{ return data.top(); } } /* min */ T min(){ if(data.empty()){ cerr << "Empty stack!" << endl; return T(NULL); } else{ return minData.top(); } } };


3.3 Imagine a (literal) stack of plates. If the stack gets too high, it might topple. Therefore, 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. SetOfStacks 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 woould 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.

/* solution for question 3.3 */ template <class T> class SetOfStacks{ private: vector<vector<T> > data; // stores data int singleSize; // size of each stack int size; // current size of SetOfStacks int num; // number of stacks public: /* constructor */ SetOfStacks(int _singleSize = 100) : singleSize(_singleSize), size(0), num(0){} /* push */ void push(T &x){ if(size + 1 > num * singleSize){ vector<T> row; row.push_back(x); data.push_back(row); size++; num++; } else{ data[num-1].push_back(x); size++; } } /* pop */ void pop(){ if(0 == size){ cerr << "Empty stack." << endl; } else{ data[num-1].erase(data[num-1].end()-1); size--; if(size == (num - 1) * singleSize){ data.erase(data.end()-1); num--; } } } /* pop at */ void popAt(int index){ if(index < 0 || index >= size){ cerr << "Out of stack." << endl; } else{ if(index == size-1){ pop(); } else{ // copy the remained data vector<T> tmp; for(int i = 0; i < data.size(); ++i){ for(int j = 0; j < data[i].size(); ++j){ if(i*singleSize + j != index){ tmp.push_back(data[i][j]); } } } // clear data.clear(); size = 0; // remind to reset size and num num = 0; // reset for(int i = 0; i < tmp.size(); ++i){ push(tmp[i]); } } } } /* top */ T top(){ if(0 == size){ cerr << "Empty stack." << endl; return T(NULL); } else{ return data[num-1][size-(num-1)*singleSize-1]; } } /* output */ void output(){ for(int i = 0; i < data.size(); ++i){ for(int j = 0; j < data[i].size(); ++j){ cout << data[i][j] << " "; } cout << endl; } } };


3.4 In the classic problem of the Towers of Hanoi, you have 3 rods and N disks of different sizes which can slide onto any tower. The puzzle starts with disks sorted in ascending 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.

/* solution for question 3.4 */ void hanoi(stack<int> &from, int n, stack<int> &to, stack<int> &by, string fromName, string toName, string byName){ if(n <= 0)return; hanoi(from, n-1, by, to, fromName, byName, toName); if(!from.empty()){ cout << "move 1 plate from " << fromName << "(" << from.top() << ")" << " to " << toName << "(" << (to.empty() ? -1 : to.top()) << ")" << endl; to.push(from.top()); from.pop(); hanoi(by, n-1, to, from, byName, toName, fromName); } }


3.5 Implement a MyQueue class which implements a queue using two stacks.

/* solution for question 3.5 */ template <class T> class MyQueue{ private: stack<T> first; stack<T> second; public: /* constructor */ MyQueue(){ //first.clear(); //second.clear(); } /* push */ void push(T &x){ first.push(x); } /* pop */ void pop(){ if(first.empty() && second.empty()){ cerr << "Empty queue." << endl; return; } // move data from first to second if(second.empty()){ while(!first.empty()){ T x = first.top(); second.push(x); first.pop(); } } second.pop(); } /* front */ T front(){ if(first.empty() && second.empty()){ cerr << "Empty queue." << endl; return T(NULL); } // move data from first to second if(second.empty()){ while(!first.empty()){ T x = first.top(); second.push(x); first.pop(); } } return second.top(); } /* back */ T back(){ if(first.empty() && second.empty()){ cerr << "Empty queue." << endl; return T(NULL); } // move data from first to second if(first.empty()){ while(!second.empty()){ T x = second.top(); first.push(x); second.pop(); } } return first.top(); } };


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.
/* solution for question 3.6 */
template <class T>
void stack_sort(stack<T> &myStack){
	stack<T> tmpStack;
	while(!myStack.empty()){
		if(tmpStack.empty()){
			tmpStack.push(myStack.top());
			myStack.pop();
		}
		else{
			// swap the top of myStack and the top of tmpStack
			if(myStack.top() > tmpStack.top()){
				T tmp = myStack.top();
				myStack.pop();
				myStack.push(tmpStack.top());
				tmpStack.pop();
				myStack.push(tmp);
			}
			else{
				tmpStack.push(myStack.top());
				myStack.pop();
			}
		}
	}

	// reset myStack
	while(!tmpStack.empty()){
		myStack.push(tmpStack.top());
		tmpStack.pop();
	}
}

说明:版权所有,转载请注明出处。 Coder007的博客
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值