利用一个数组实现两个栈是数据结构中的一道经典面试题,那么如何来求解呢?

大多数人为了方便都采取了静态实现方式,但是这种方式不能进行扩容,不够完美。博主利用C++尝试了一下动态实现。

首先,通过了解栈的特点(后进先出),可以想到如下几个方案:

First>>将数组的下标为奇数的位置都插入栈1的元素,数组的下标为偶数的位置都插入栈2的元素。这种方式插入删除时需要利用数组的下标来控制对栈1操作还是栈2操作,这点虽然简单易行。但是,在进行扩容时却需要将两个栈同步扩容,这样下来,就会浪费许多不必要的空间。

一个数组实现两个栈_数组

Second>>将数组的中间两个位置作为两个栈的栈顶,向数组两边进行插入删除。这种做法虽然可以节省空间,但是试想这样一个场景,如果向后插入的那个栈插入满了,而前面的那个栈没有满,那么我们就要绕到数组的开始去进行插入,这样写起来代码的可读性就不高,而且拷贝构造函数也不好实现,还容易引发一系列不必要的问题。

一个数组实现两个栈_数组_02

Third>>最后考虑到的是将数组的开始位置和结束位置作为两个栈的栈底,两个栈均向中间插入删除,当两个栈的栈顶相遇时,进行扩容。拷贝构造时,为了节省空间,将两个栈进行分开拷贝。这样就避免了出现前面提到的问题。

一个数组实现两个栈_数组_03

代码实现:

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;
};

程序虽然实现了,但是还是存在许多小瑕疵,希望大家指正~~~~~~~~~~一个数组实现两个栈_数组_04