一个
数组实现共享栈是一个经典的算法,这些年也备受笔试/面试的青睐,其核心思想不难,但是对于临界点的把握是比较容易出错的,下面列举出两种常用方法。
1.奇偶占位法
如下图所示,对stack1进行偶数位压栈,对stack2进行奇数位压栈。top即栈顶,分别指向当前栈中最后一个元素的下一个将要压栈的位置。栈的数据结构较为简单,这里就不对其push、pop等操作过多描述,对应此图进行操作是很容易实现的。
此方法的不足在于,如果stack1插入了很多元素,而stack2插入元素极少,那么将会浪费很多资源,造成浪费,因此不推荐大家使用。
#pragma once
#include <iostream>
#include <assert.h>
using namespace std;
template<class T>
class arr_2_stack
{
public:
arr_2_stack()
:_arr(NULL)
,_top1(0)
,_top2(1)
,_size(0)
,_capacity(0)
{}
~arr_2_stack()
{
delete[] _arr;
}
void push(const T& data,int flag);//入栈
void pop(int flag );//出栈
size_t size(int flag);//栈的大小
T& top(int flag = 0);//栈顶元素
bool empty(int flag);//判断栈空
const size_t length(int flag)const;//栈的下标
void PrintStack(int flag);//打印
protected:
//扩容
void CheckCapacity();
private:
T* _arr;
size_t _top1;//栈1的栈顶
size_t _top2;//栈2的栈顶
size_t _size;//有效元素的个数
size_t _capacity;//容量
};
template<class T>
//扩容
void arr_2_stack<T>::CheckCapacity()
{
if (_size >= _capacity)
{
size_t NewCapacity = _capacity * 2 + 3;
T* tmp = new T[NewCapacity];
for (size_t idx = 0; idx < _size; ++idx)
{
tmp[idx] = _arr[idx];
}
delete[] _arr;
_arr = tmp;
_capacity = NewCapacity;
}
}
template<class T>
T& arr_2_stack<T>::top(int flag)
{
//stack1
if (flag == 0)
{
assert(_top1 > 0);
return _arr[_top1 - 2];
}
//stack2
else
{
assert(_top2 > 1);
return _arr[_top2 - 2];
}
}
template<class T>
void arr_2_stack<T>::push(const T& data, int flag)
{
CheckCapacity();
//stack1
if (flag == 0)
{
_arr[_top1] = data;
_top1 += 2;
if (_top1 > _top2)
{
_size += 2;
}
}
//stack2
else
{
_arr[_top2] = data;
_top2 += 2;
if (_top2 > _top1)
{
_size += 2;
}
}
}
template<class T>
size_t arr_2_stack<T>::size(int flag)
{
if (flag == 0)
return _top1 >> 1;
else
return (_top2 - 1) >> 1;
}
template<class T>
const size_t arr_2_stack<T>::length(int flag)const
{
if (flag == 0)
{
return _top1 - 2;
}
else
return _top2 - 2;
}
template<class T>
void arr_2_stack<T>::PrintStack(int flag)
{
if (flag == 0)
{
if (_top1 <= 0)
{
cout << "Stack1 empty..." << endl;
return;
}
for (size_t idx = 0; idx <= length(flag); idx += 2)
cout << _arr[idx] << " ";
cout << endl;
}
else
{
if (_top2 <= 1)
{
cout << "Stack2 empty..." << endl;
return;
}
for (size_t idx = 1; idx <= length(flag); idx += 2)
cout << _arr[idx] << " ";
cout << endl;
}
}
template<class T>
bool arr_2_stack<T>::empty(int flag)
{
if (flag == 0)
return _top1 == 0;
else
return _top2 == 1;
}
template<class T>
void arr_2_stack<T>::pop(int flag)
{
if (flag == 0)
{
if (_top1 <= 0)
{
cout << "Stack1 empty" << endl;
return;
}
_top1 -= 2;
if (_top1 > _top2)
_size -= 2;
}
else
{
if (_top2 <= 0)
{
cout << "Stack2 empty" << endl;
return;
}
_top2 -= 2;
if (_top2 > _top1)
_size -= 2;
}
}
2.首尾相遇法
没有一张图解决不了的问题,如果有,那就两张。首尾相遇的算法思想也很简单,但是在扩容的时候要对stack2做特殊处理,将stack2的数据后移的同时,将stack2的栈顶_top2也后移。
#pragma once
#include <iostream>
#include <assert.h>
using namespace std;
template<class T>
class arr_2_stack
{
public:
arr_2_stack()
:_arr(NULL)
,_top1(0)
,_top2(0)
,_capacity(0)
{}
~arr_2_stack()
{
delete[] _arr;
}
void push(const T& data,int flag);//入栈
void pop(int flag );//出栈
const size_t size(int flag)const;//栈的大小
T& top(int flag = 0);//栈顶元素
bool empty(int flag);//判断栈空
const size_t length(int flag)const;//栈的下标
void PrintStack(int flag);//打印
protected:
//扩容
void CheckCapacity();
private:
T* _arr;
int _top1;//栈1的栈顶
int _top2;//栈2的栈顶
int _capacity;//容量
};
template<class T>
void arr_2_stack<T>::CheckCapacity()
{
if (_top1 == _top2)
{
int NewCapacity = 2 * _capacity + 2;
T* tmp = new T[NewCapacity];
for (size_t idx = 0; idx < _top1; ++idx)
tmp[idx] = _arr[idx];
int k = _capacity - 1;
for (int idx = NewCapacity - 1; k > _top2; --idx, --k)
{
tmp[idx] = _arr[k];
}
delete[] _arr;
_arr = tmp;
size_t count = 0;//stack2的元素个数
if (_capacity)
{
count = _capacity - 1 - _top2;
}
_capacity = NewCapacity;
_top2 = _capacity - 1 - count;//修改stack2的栈顶
}
}
template<class T>
void arr_2_stack<T>::push(const T& data, int flag)
{
CheckCapacity();
//stack1
if (flag == 0)
_arr[_top1++] = data;
else
_arr[_top2--] = data;
}
template<class T>
void arr_2_stack<T>::pop(int flag)
{
if (flag == 0)
{
if (_top1 <= 0)
{
cout << "Stack1 empty..." << endl;
return;
}
_top1--;
}
else
{
if (_top2 == _capacity - 1)
{
cout << "Stack2 empty..." << endl;
return;
}
_top2--;
}
}
template<class T>
const size_t arr_2_stack<T>::size(int flag)const
{
//stack1
if (flag == 0)
return _top1;
else
return _capacity - 1 - _top2;
}
template<class T>
T& arr_2_stack<T>::top(int flag)
{
if (flag == 0)
return _arr[_top1 - 1];
else
return _arr[_top2 + 1];
}
template<class T>
const size_t arr_2_stack<T>::length(int flag)const
{
if (flag == 0)
{
return _top1 - 1;
}
else
return _top2 + 1;
}
template<class T>
bool arr_2_stack<T>::empty(int flag)
{
if (flag == 0)
return _top1 == 0;
else
return _top2 == (_capacity - 1);
}
template<class T>
void arr_2_stack<T>::PrintStack(int flag)
{
if (flag == 0)
{
if (_top1 <= 0)
{
cout << "Stack1 empty..." << endl;
return;
}
for (size_t idx = 0; idx <= length(flag); ++idx)
cout << _arr[idx] << " ";
cout << endl;
}
else
{
if (_top2 == _capacity - 1)
{
cout << "Stack2 empty..." << endl;
return;
}
for (size_t idx = _capacity - 1; idx > length(flag) ; --idx)
cout << _arr[idx] << " ";
cout << endl;
}
}
//两种方法的测试用例
#include "Array2stack.h"
void Test1()
{
/*arr_2_stack<int> _s;
_s.push(1, 0);
_s.push(2, 0);
_s.push(3, 0);
_s.push(10, 1);
_s.push(20, 1);
_s.push(30, 1);
_s.push(40, 1);
cout << _s.size(0) << endl;
cout << _s.size(1) << endl;
cout << _s.top(0) << endl;
cout << _s.top(1) << endl;
cout << _s.length(0) << endl;
cout << _s.length(1) << endl;
_s.PrintStack(0);
_s.PrintStack(1);
cout << _s.empty(0) << endl;
cout << _s.empty(1) << endl;
_s.PrintStack(0);
_s.PrintStack(1);*/
}
void Test2()
{
arr_2_stack<int> _s;
_s.push(1, 0);
_s.push(2, 0);
_s.push(3, 0);
_s.push(10, 1);
_s.push(20, 1);
_s.push(30, 1);
_s.push(40, 1);
_s.push(20, 1);
_s.push(30, 1);
_s.push(40, 1);
_s.PrintStack(0);
_s.PrintStack(1);
/*_s.pop(0);
_s.pop(0);
_s.pop(1);
_s.PrintStack(0);
_s.PrintStack(1);*/
cout << _s.size(0) << endl;
cout << _s.size(1) << endl;
cout << _s.top(0) << endl;
cout << _s.top(1) << endl;
cout << _s.empty(0) << endl;
cout << _s.empty(1) << endl;
}
int main()
{
//Test1();
Test2();
system("pause");
return 0;
}