【面试题】一个数组实现两个栈

思路一:在数组中,一个栈从左往右增长,另一个栈从右往左增长。

思路二:采用交叉索引法,1号栈所占数组索引1,3,5,7.....;2号栈所占数组索引2,4,6,8.......

思路一必须给定数组长度,不易动态增长,但可通过扩容实现动态增长。

思路二比思路一容易动态增长,但空间利用率低,对两个栈实现了公平。

思路一的实现如下:

template<class T>
class TwoStack
{
public:
	TwoStack()
		:_stacktop1(0)
		, _stacktop2(0)
		, _arr(NULL)
		, _size(0)
		, _capacity(0)
	{}
	TwoStack(size_t size)//设定数组大小
		:_stacktop1(0)
		, _stacktop2(size - 1)
		, _arr(new T[size])
		, _size(size)
		, _capacity(size)
	{}
	~TwoStack()
	{
		if (_arr)
		{
			delete[] _arr;
		}
	}
public:
	//indx判断需要进行插入、删除等操作的栈是哪个栈,设置indx为0时是_stack1,为1时是_stack2
	void CheckCapacity();
	void Push(size_t indx, const T& x);
	void Pop(size_t indx);
	bool Empty(size_t indx);
	size_t Size(size_t indx);
	T& Top(size_t indx);
	void PrintArr();
private:
	size_t _stacktop1;//栈1栈顶位置
	size_t _stacktop2;//栈2栈顶位置
	T* _arr;
	size_t _size;
	size_t _capacity;
};
template<class T>
void TwoStack<T>::CheckCapacity()
{
	if (_stacktop1 - 1 == _stacktop2)//当发生交叉时,则数组已满
	{
		_capacity = 2 * _capacity + 3;
		T* tmp = new T[_capacity];
		for (size_t i = 0; i < _stacktop1; i++)
		{
			tmp[i] = _arr[i];
		}
		for (size_t i = 1; i < _size - _stacktop2; i++)//_size - _stacktop2 - 1为栈2的大小
		{
			tmp[_capacity - i] = _arr[_size - i];
		}
		delete[] _arr;
		_arr = tmp;
		_size = _capacity;//更新数组大小
		_stacktop2 = _size - _stacktop2 - 1;//更新栈2的栈顶位置,指向下一个栈存放的下标
	}
}
template<class T>
void TwoStack<T>::Push(size_t indx, const T& x)
{
	CheckCapacity();
	if (indx == 0)
	{
		_arr[_stacktop1] = x;
		_stacktop1++;
	}
	if (indx == 1)
	{
		_arr[_stacktop2] = x;
		_stacktop2--;
	}
}
template<class T>
void TwoStack<T>::Pop(size_t indx)
{//注意在入栈后_stacktop1和_stacktop2指向即将下一个进栈的位置
	assert(_size);
	if (indx == 0)
	{
		if (_stacktop1 == 0)
		{
			cout << "Stack1 is empty!" << endl;
		}
		else
		{
			_arr[_stacktop1 - 1] = '0';
			--_stacktop1;
		}
	}
	if (indx == 1)
	{
		if (_stacktop2 == _size - 1)
		{
			cout << "Stack2 is empty!" << endl;
		}
		else
		{
			_arr[_stacktop2 + 1] = '0';
			++_stacktop2;
		}
	}
}
template<class T>
bool TwoStack<T>::Empty(size_t indx)
{
	if (indx == 0)
	{
		return _stacktop1 == 0;
	}
	if (indx == 1)
	{
		return _stacktop2 == _size - 1;
	}
}
template<class T>
size_t TwoStack<T>::Size(size_t indx)
{
	if (indx == 0)
	{
		return _stacktop1;
	}
	if (indx == 1)
	{
		return _size - _stacktop2 - 1;
	}
	return -1;
}
template<class T>
T& TwoStack<T>::Top(size_t indx)
{
	assert(_size);
	if (indx == 0)
	{
		return _arr[_stacktop1 - 1];
	}
	if (indx == 1)
	{//_stacktop2指向即将下一个进栈的位置
		return _arr[_stacktop2 + 1];
	}
	--_size;
}
template<class T>
void TwoStack<T>::PrintArr()
{
	if (_size == 0)
	{
		cout << "Stack is empty!";
	}
	else
	{
		for (size_t i = 0; i < _size; i++)
		{
			cout << _arr[i] << "  ";
		}
		cout << endl;
	}
}

思路二的实现如下:

template<class T>
class TwoStack
{
public:
	TwoStack()
		:_stacktop1(-1)
		, _stacktop2(-2)
		, _array(new T[MAX_SIZE])
	{}
	~TwoStack()
	{
		if (_array)
		{
			delete[] _array;
		}
	}
public:
	//indx判断需要进行插入、删除等操作的栈是哪个栈,设置indx为1时是_stack1,为0时是_stack2
	void Push(size_t indx, const T& x);
	void Pop(size_t indx);
	bool Empty(size_t indx);
	size_t Size(size_t indx);
	T& Top(size_t indx);
	void PrintArr();
private:
	int _stacktop1;//栈1栈顶位置
	int _stacktop2;//栈2栈顶位置
	T* _array;
};
template<class T>
void TwoStack<T>::Push(size_t indx, const T& x)
{
	if (indx == 1)
	{
		if (_stacktop1 + 2 >= MAX_SIZE)
		{
			cout << "Stack1 is full!" << endl;
		}
		else
		{
			_stacktop1 += 2;
			_array[_stacktop1] = x;
		}
	}
	if (indx == 0)
	{
		if (_stacktop2 + 2 >= MAX_SIZE)
		{
			cout << "Stack2 is full!" << endl;
		}
		else
		{
			_stacktop2 += 2;
			_array[_stacktop2] = x;
		}
	}
}
template<class T>
void TwoStack<T>::Pop(size_t indx)
{
	if (indx == 1)
	{
		if (_stacktop1 < 0)
		{
			cout << "Stack1 is empty!" << endl;
		}
		else
		{
			_stacktop1 -= 2;
		}
	}
	if (indx == 0)
	{
		if (_stacktop1 < 1)
		{
			cout << "Stack2 is empty!" << endl;
		}
		else
		{
			_stacktop2 -= 2;
		}
	}
}
template<class T>
bool TwoStack<T>::Empty(size_t indx)
{
	if (indx == 1)
	{
		return _stacktop1 == 0;
	}
	if (indx == 0)
	{
		return _stacktop2 == 1;
	}
}
template<class T>
size_t TwoStack<T>::Size(size_t indx)
{
	if (indx == 1)
	{
		return (_stacktop1 + 1) / 2;
	}
	if (indx == 0)
	{
		return (_stacktop2 + 2) / 2;//由于_stacktop2为奇数,且/运算,故+2
	}
}
template<class T>
T& TwoStack<T>::Top(size_t indx)
{
	if (indx == 1)
	{
		return _array[_stacktop1];
	}
	if (indx == 0)
	{
		return _array[_stacktop2];
	}
}
template<class T>
void TwoStack<T>::PrintArr()
{
	if (Empty(0))
	{
		cout << "Stack1 is empty!" << endl;
	}
	else if(Empty(0))
	{
		cout << "Stack2 is empty!" << endl;
	}
	else
	{
		cout << "Stack1:";
		for (int i = 1; i <= _stacktop1; i += 2)
		{
			cout << _array[i]<<"  ";
		}
		cout << '\n' << "Stack2:";
		for (int i = 0; i <= _stacktop2; i += 2)
		{
			cout << _array[i]<<"  ";
		}
		cout << endl;
	}
}

测试用例如下:

void Test()
{
	TwoStack<string> s1;
	s1.Push(1, "aaaaa");
	s1.Push(1, "bbbbb");
	s1.Push(1, "lllll");
	s1.Push(0, "yyyyy");
	s1.Push(0, "fffff");
	s1.Push(0, "ggggg");
	s1.PrintArr();

	s1.Pop(1);
	s1.PrintArr();
	s1.Pop(0);
	s1.PrintArr();
	cout << "empty: "<<s1.Empty(1) << "----" << s1.Empty(0) << endl;
	cout << "size: " << s1.Size(1) << "----" << s1.Size(0) << endl;
	cout << "top: " << s1.Top(1) << "----" << s1.Top(0) << endl;
	s1.Pop(1);
	s1.Pop(1);
	s1.Pop(1);
	s1.PrintArr();
}

在面试时,由于时间紧迫,我们可以不用实现动态的,只需实现静态的数组,并实现push()和pop().