Chapter 3 | Stacks and Queues--实现数据结构模拟一个栈由几个子栈组成,并可以在指定子栈上进行出栈操作

来源:互联网 发布:ubuntu install pip 编辑:程序博客网 时间:2024/06/05 15:59
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;elsereturn Stacks.back();}/*返回指定栈*/Stack* SetOfStacks::getStack(int index){if ((index < 0) || (index >= ((int)Stacks.size()-1)))return NULL;elsereturn 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];}//指定子栈进行 popvoid 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 6setofstacks.popAt(1);  //stack:1 2 3 5 6setofstacks.popAt(1);  //stack:1 2 5 6setofstacks.pop();     //stack:1 2 5setofstacks.pop();     //stack:1 2/*setofstacks.pop();setofstacks.pop();setofstacks.pop();*/cout << setofstacks.top() << endl;  //output:2return 0;}

0 0
原创粉丝点击