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 newstack when the previous stack exceeds some threshold. Implement adata structure SetOfStacks that mimics this. SetOfStacks should be composed of several stacks, and should create a new stack once theprevious one exceeds capacity. SetOfStacks.push() andSetOfStacks.pop() should behave identically to a single stack(that is, pop() should return the same values as it would if therewere just a single stack).
FOLLOW UP
Implement a function popAt(int index) which performs a pop operationon a specific sub-stack.
译文:把栈想象成一碟盘子,如果盘子叠的太高,就会倾倒。因此,在实际生活中,在前面的栈超出一定高度时,我们就会开始另一个新栈。实现数据结构 SetOfStacks 来模拟这种情况,SetOfStacks 由几个栈组成,当前面一个栈超出容量时,需要创建一个新栈来存放数据。SetOfStacks.push() andSetOfStacks.pop() 的行为应该和只有一个栈时一样。
进一步的,实现函数 popAt(int index) 在指定子栈上进行 pop 操作。
这里用了 STL 中的 序列式容器vector,vector 内部实现则参见 vector 内部机制。
#include<iostream>
#include<vector> //STL
#include<assert.h>
using namespace std;
class SetOfStacks;
class Stack
{
public:
Stack(int Size);
~Stack(void);
void push(int val);
void pop(void);
int top(void);
bool isempty(void);
bool isfull(void);
friend class SetOfStacks; //友元类
private:
int *Data;
int current;
int capacity;
};
Stack::Stack(int Size)
{
Data = new int[Size];
current = -1;
capacity = Size;
}
Stack::~Stack(void)
{
if (Data)
delete[] Data;
}
void Stack::push(int val)
{
Data[++current] = val;
}
void Stack::pop(void)
{
--current;
}
int Stack::top(void)
{
return Data[current];
}
bool Stack::isempty(void)
{
return (-1 == current);
}
bool Stack::isfull(void)
{
return (current == (capacity - 1));
}
//SetOfStacks数据结构
class SetOfStacks
{
public:
SetOfStacks(Stack &s);
~SetOfStacks(void);
Stack* getLastStack(void);
Stack* getStack(int index);
void push(int val);
void pop(void);
int top(void);
void popAt(int index);
private:
vector<Stack*> Stacks; //from STL
};
SetOfStacks::SetOfStacks(Stack &s)
{
Stacks.push_back(&s);
}
SetOfStacks::~SetOfStacks(void)
{
}
/*返回最后一个栈*/
Stack* SetOfStacks::getLastStack(void)
{
if (0 == Stacks.size())
return NULL;
else
return Stacks.back();
}
/*返回指定栈*/
Stack* SetOfStacks::getStack(int index)
{
if ((index < 0) || (index >= ((int)Stacks.size()-1)))
return NULL;
else
return Stacks[index];
}
void SetOfStacks::push(int val)
{
Stack* pStack = getLastStack();
assert(NULL != pStack);
if (pStack->isfull()) //栈满,则创建新栈
{
Stack* stack = new Stack(sizeof(Stack));
stack->Data = new int[pStack->capacity];
stack->current = -1;
stack->capacity = pStack->capacity;
stack->push(val);
Stacks.push_back(stack); //添加到vector
}
else
{
pStack->push(val);
}
}
void SetOfStacks::pop(void)
{
Stack* pStack = getLastStack();
assert(NULL != pStack);
pStack->pop();
if (pStack->isempty()) //当前栈为空,则销毁
{
delete[] pStack->Data; //释放空间
Stacks.pop_back(); //vector 析构
}
}
int SetOfStacks::top(void)
{
Stack* pStack = getLastStack();
assert(NULL != pStack);
return pStack->Data[pStack->current];
}
//指定子栈进行 pop
void SetOfStacks::popAt(int index)
{
Stack* pStack = getStack(index);
assert(NULL != pStack);;
pStack->pop();
if (pStack->isempty()) //pop后指定栈为空
{
delete[] pStack->Data;
//销毁指定栈,并将后面子栈前移
for (unsigned int i = index; i < (Stacks.size() - 1); ++i)
{
if (Stacks[i + 1] != NULL)
Stacks[i] = Stacks[i + 1];
}
Stacks.pop_back(); //前移后,销毁最后一个
}
}
上面最指定子栈 pop 的函数 popAt 其功能是将指定位置的子栈元素弹出,当该子栈为空(没有元素)时,则将其后面的子栈前移,并销毁最后一个子栈,这样保证 pop 中间指定子栈后,其总栈在逻辑上还是连续的。
如不借用STL中的 vector,也可自行设计一个链表用来存储子栈。
测试代码及结果:
int main()
{
Stack stack(2);
SetOfStacks setofstacks(stack);
setofstacks.push(1);
setofstacks.push(2);
setofstacks.push(3);
setofstacks.push(4);
setofstacks.push(5);
setofstacks.push(6); //stack:1 2 3 4 5 6
setofstacks.popAt(1); //stack:1 2 3 5 6
setofstacks.popAt(1); //stack:1 2 5 6
setofstacks.pop(); //stack:1 2 5
setofstacks.pop(); //stack:1 2
/*setofstacks.pop();
setofstacks.pop();
setofstacks.pop();*/
cout << setofstacks.top() << endl; //output:2
return 0;
}