栈是限定仅在表尾进行插入和删除操作的线性表,允许插入和删除的一端称为栈顶,另一端则为栈底。仅能对栈顶元素直接进行操作。
如图所示,初始状态下栈里有三个元素。这三个元素进入栈的顺序必然是x,y,z,出栈顺序必然是z,y,x(这里我们不考虑其他元素)。可见,先进入的元素x由于最先进入栈内,被其他进入的元素压在栈底,而最后出来,所以我们说栈具有先进后出的特性。
关于栈的使用,最常见的是括号匹配,若是左括号则入栈,遇到右括号则和栈顶元素匹配,若不对应,则匹配错误。
对于栈的操作,我们可以简单谈谈。
入栈——将元素放到栈顶;出栈——栈顶元素弹出,将栈顶的下一层元素设置为栈顶。关于这两个操作,都涉及到了栈顶位置的移动,我们在实现的时候采用指针来控制。
关于顺序栈的实现如下:
#include <iostream>
using namespace std;
const int StackSize = 1000;
template <class T>
class SeqStack
{
public:
SeqStack(); // 构造
~SeqStack(){ } // 析构
void push(T x); // 入栈
T pop(); // 出栈并获取栈顶元素
T getTop(); // 获取栈顶元素
int empty();// 判断栈是否为空
private:
T data[StackSize];
int top; // 栈顶指针,为元素下标
};
template <class T>
SeqStack<T>::SeqStack()
{
top = -1; // -1下标并不存在,表示空栈
}
template <class T>
void SeqStack<T>::push(T x)
{
// 顺序栈事先分配了最大空间
// 上溢条件易被忽略
if(top == StackSize - 1) throw"上溢";
// 入栈下标+1
data[++top] = x;
}
template <class T>
T SeqStack<T>::pop()
{
// 出栈前需要判断栈是否为空
// 空栈无栈顶元素可出栈
if(top == -1) throw"下溢";
return data[top--]; //先弹出栈顶元素,再移动栈顶指针
}
template <class T>
T SeqStack<T>::getTop()
{
if(top == -1) throw"下溢";
return data[top];
}
template <class T>
int SeqStack<T>::empty()
{
if (top == -1 ) return 1;
else return 0;
}
int main()
{
SeqStack<int> ss;
ss.push(5); ss.push(8); ss.push(9); ss.push(10);
int m = ss.pop();
cout << "栈顶元素为: " << m ;
m = ss.pop();
cout << " " << m ;
m = ss.pop();
cout << " " << m ;
m = ss.pop();
cout << " " << m ;
return 0;
}
------------------------19.6.1 待续----------------------------
链栈的构造方式和单链表相似,却简单得多,唯一复杂的则是析构函数。
#include <iostream>
using namespace std;
template <class T>
struct Node
{
T data;
Node<T> *next;
};
template <class T>
class LinkStack
{
public:
LinkStack();
~LinkStack();
void Push(T x); // 入栈
T Pop(); // 获取栈顶元素并将其出栈
T GetTop(); // 获取栈顶元素
bool Empty(); //判断是否为空栈
private:
Node<T> *head; // 栈顶指针
};
template <class T>
LinkStack<T>::LinkStack()
{
head = NULL;
}
template <class T>
LinkStack<T>::~LinkStack()
{
// 删除所有结点
while (head)
{
Node<T> *p = head -> next;
delete head;
head = p;
}
}
template <class T>
void LinkStack<T>::Push(T x)
{
// 入栈操作
// 更新当前栈顶指针
// 原先的栈顶指针为当前栈顶指针的下一个结点
Node<T> *p = new Node<T>;
p -> data = x;
p -> next = head;
head = p;
}
template <class T>
T LinkStack<T>::Pop()
{
if(head == NULL) throw "空栈";
T x = head -> data;
// 这里必须借助p指针释放旧的栈顶指针内存空间
// 否则head为NULL
Node<T> *p = head;
head = head -> next;
delete p;
return x;
}
template <class T>
T LinkStack<T>::GetTop()
{
if(head == NULL) throw"空栈";
return head -> data;
}
template <class T>
bool LinkStack<T>::Empty()
{
if(head == NULL) return 1;
else return 0;
}
int main()
{
LinkStack<int> ls;
ls.Push(1); ls.Push(2); ls.Push(3);
int x = ls.Pop();
cout << "栈顶元素为" << x << endl;
x = ls.GetTop();
cout << "栈顶元素为" << x << endl;
string str = ((ls.Empty()==1)? "空" : "非空");
cout << "栈空否? " << str << endl;
ls.Pop();
ls.Pop();
str = ((ls.Empty()==1)? "空" : "非空");
cout << "栈空否? " << str << endl;
return 0;
}
------------------------19.6.2 待续----------------------------