利用一个数组实现两个栈是数据结构中的一道经典面试题,那么如何来求解呢?
大多数人为了方便都采取了静态实现方式,但是这种方式不能进行扩容,不够完美。博主利用C++尝试了一下动态实现。
首先,通过了解栈的特点(后进先出),可以想到如下几个方案:
First>>将数组的下标为奇数的位置都插入栈1的元素,数组的下标为偶数的位置都插入栈2的元素。这种方式插入删除时需要利用数组的下标来控制对栈1操作还是栈2操作,这点虽然简单易行。但是,在进行扩容时却需要将两个栈同步扩容,这样下来,就会浪费许多不必要的空间。
Second>>将数组的中间两个位置作为两个栈的栈顶,向数组两边进行插入删除。这种做法虽然可以节省空间,但是试想这样一个场景,如果向后插入的那个栈插入满了,而前面的那个栈没有满,那么我们就要绕到数组的开始去进行插入,这样写起来代码的可读性就不高,而且拷贝构造函数也不好实现,还容易引发一系列不必要的问题。
Third>>最后考虑到的是将数组的开始位置和结束位置作为两个栈的栈底,两个栈均向中间插入删除,当两个栈的栈顶相遇时,进行扩容。拷贝构造时,为了节省空间,将两个栈进行分开拷贝。这样就避免了出现前面提到的问题。
代码实现:
template<class T> class TwoStack { public: TwoStack() :_a(0) ,_top1(0) ,_top2(0) ,_capacity(0) { } ~TwoStack() { if(_a != NULL) { delete [] _a; } } /*TwoStack(const TwoStack<T>& ts) :_a(new T[ts._capacity]) ,_top1(ts._top1) ,_top2(ts._top2) ,_capacity(ts._capacity) { for(size_t i = 0; i< _capacity-1; i++) { _a[i] = ts._a[i]; } }*/ TwoStack( const TwoStack<T>& ts) :_a(new T[ ts._capacity -ts._top2 +ts._top1])//size+1 ,_top1(ts._top1) ,_top2(_top1) ,_capacity( ts._capacity -ts._top2 +ts._top1) { size_t j = ts._capacity - 1; for(size_t i = 0; i<=_top1; i++) { _a[i] = ts._a[i]; } for(size_t i = _capacity-1; i >_top2; i--,j--) { _a[i] = ts._a[j]; } } TwoStack<T>& operator= (TwoStack<T> ts) { _top1 = ts._top1; _top2 = ts._top2; _capacity = ts._capacity; swap(_a,ts._a); return *this; } void Push(const T& x,int choice) { _CheckCapacity(); if(choice == 0) { _a[_top1++] = x; } if(choice ==1) { _a[_top2--] = x; } } void Pop(int choice) { if(choice == 0) { assert(_top1 > 0); _top1--; } if(choice == 1) { assert(_top2 <_capacity-1); _top2++; } } T& Top(int choice) { if(choice == 0) { assert(_top1 > 0); return _a[_top1-1]; } if(choice == 1) { assert(_top2 <_capacity-1); return _a[_top2+1]; } } bool Empty(int choice) { if(choice == 0) { return _top1 == 0; } if(choice == 1) { return _top2 ==_capacity-1; } } size_t Size(int choice) { if(choice == 0) { return _top1; } if(choice == 1) { return _capacity-1-_top2; } } void Print() { cout << "栈0为:"; for(size_t i = 0; i<_top1; i++) { cout << _a[i] <<" "; } cout<<endl; cout << "栈1为:"; for(size_t j = _capacity-1; j>_top2; --j) { cout << _a[j] << " "; } cout <<endl<<endl; } protected: void _CheckCapacity() { if(_a == NULL) { _capacity = 3; _a = new T[_capacity]; _top2 = _capacity - 1;//此时不要忘了给_top2赋值,构造时给的是0 return; } if(_top1 == _top2) { size_t j = 0; size_t oldCapacity = _capacity;//记住原来的 _capacity = 2 * _capacity; T* tmp = new T[_capacity]; for(size_t i = 0;i <_top1;i++)//正向拷贝 { tmp[i] = _a[i]; } for(size_t i = _capacity-1, j = oldCapacity-1; j >_top2; i--, j--)//反向拷贝 { tmp[i] = _a[j]; } delete [] _a; _a = tmp; _top2 = (_capacity-1) - (oldCapacity-1-_top2);// 最后一个下标-元素个数 } } protected: T* _a; size_t _top1; size_t _top2; size_t _capacity; };