栈的限定是仅在表尾进行插入和删除操作的线性表.允许插入和删除的一端称为栈顶,另一端称为栈底。栈具有后进先出的特性.栈的实现同样有顺序栈和链栈两种。
1)顺序栈:
栈的顺序实现比较简单,这里我们讨论一种两栈共享栈空间的顺序栈,它可以避免两个栈时,一个栈满,而另一个栈还有大量存储空间的情况.
#define MAX_SIZE 1024
template <class T>
class CBothStack
{
private:
T m_array[MAX_SIZE];
int m_top1;
int m_top2;
public:
CBothStack();
~CBothStack(){}
void Push(int i, T value);
T Pop(int i);
bool Empty(int i);
T GetTop(int i);
void PrintStack();
};
template <class T>
CBothStack<T>::CBothStack()
{
m_top1 = -1;
m_top2 = MAX_SIZE;
}
template <class T>
void CBothStack<T>::Push(int i, T value)
{
// 判断栈是否已满
if((m_top2 - m_top1) == 1)
{
throw "栈满";
}
if (i == 1)
{
m_array[++m_top1] = value;
}else
{
m_array[--m_top2] = value;
}
}
template<class T>
T CBothStack<T>::Pop(int i)
{
if (i == 1)
{
if (m_top1 == - 1)
{
throw "栈1没有元素";
}
T value = m_array[m_top1--];
return value;
}else
{
if (m_top2 == MAX_SIZE)
{
throw "栈2没有元素";
}
T value = m_array[m_top2++];
return value;
}
}
template <class T>
T CBothStack<T>::GetTop(int i)
{
if (i == 1)
{
if (m_top1 == - 1)
{
throw "栈1没有元素";
}
T value = m_array[m_top1];
return value;
}else
{
if (m_top2 == MAX_SIZE)
{
throw "栈2没有元素";
}
T value = m_array[m_top2];
return value;
}
}
template <class T>
bool CBothStack<T>::Empty(int i)
{
if (i == 1)
{
return (m_top1 == -1 ? true : false);
}else
{
return (m_top2 == MAX_SIZE ? true : false);
}
}
template<class T>
void CBothStack<T>::PrintStack()
{
if (!Empty(1))
{
printf("栈1:");
int top = m_top1;
while (top >= 0)
{
printf("%d, ", m_array[top--]);
}
}
if (!Empty(2))
{
printf("栈2:");
int top = m_top2;
while (top < MAX_SIZE)
{
printf("%d, ", m_array[top++]);
}
}
}
2)链栈的实现:
链栈的操作实际上是单链表操作的简化,插入和删除只需要考虑栈顶第一个位置元素的情况.
template <class T>
struct Node
{
Node* pNextNode;
T m_value;
};
template <class T>
class CLinkStack
{
private:
Node<T>* m_top;
public:
CLinkStack();
~CLinkStack();
void Push(T value);
T Pop();
bool Empty();
T GetTop();
};
template <class T>
CLinkStack<T>::CLinkStack()
{
m_top = NULL;
}
template <class T>
CLinkStack<T>::~CLinkStack()
{
if (m_top != NULL)
{
Node<T>* s = m_top;
while (s != NULL)
{
printf("1,");
Node<T>* r = s;
s = s->pNextNode;
delete r;
}
}
m_top = NULL;
}
template <class T>
void CLinkStack<T>::Push(T value)
{
Node<T>* s = new Node<T>;
s->m_value = value;
s->pNextNode = m_top;
m_top = s;
}
template <class T>
T CLinkStack<T>::Pop()
{
if (m_top != NULL)
{
int value = m_top->m_value;
Node<T>* s = m_top;
m_top = m_top->pNextNode;
delete s;
return value;
}
throw "链栈无元素";
}
template <class T>
T CLinkStack<T>::GetTop()
{
if (m_top != NULL)
{
return m_top->m_value;
}
throw "链栈无元素";
}
template <class T>
bool CLinkStack<T>::Empty()
{
return m_top == NULL ? true : false;
}
3)顺序栈和链栈的比较
它们的基本操作的算法都需要常数时间,所以唯一可以比较的就是空间性能.顺序栈在初始化时比较指定大小的空间,且被限制,所以有空间浪费和元素限制问题.而链栈没有空间限制,只有当内存无可用时.但是链栈需要一个指针域, 耗费了额外的存储空间.所以在栈的元素个数变化较大时,链栈是适宜的,反之,应采用顺序栈.