本篇先介绍顺序栈、链栈的原理,然后介绍C++ STL栈模板的简单用法。
一、为什么引入栈这个名词
有些应用,处理的数据具有下面的特点:
1、具有线性结构,用线性表存储
2、然而,却只需要简单的操作:仅在线性表的一端进行插入和删除。
你当然可以使用前面实现过的顺序表和链表,只不过只用到其中的部分操作而已。
有好事的前辈,偏偏为它取个名字,叫“栈”,又多一个名词,多一个负担。
线性表有两种实现方式,顺序表和链表
对应的栈也有两种。
二、顺序栈
这就要分析了,用顺序表做为栈,在哪一头进行插入删除呢?
显然在下标大的那一头插入和删除都不需要移动其他数据,效率高
因此,顺序栈的插入操作(入栈)就是在表尾插入,栈的删除操作(出栈)就是在表尾删除。
#include "stdafx.h"
#include<iostream>
using namespace std;
//模板类,T是泛化类型
template<typename T>class stack
{//顺序栈
T *base;//连续空间的首地址,栈底
int listsize;//连续空间的大小
int length;//实际元素的个数
T *top;//栈顶
public:
stack()
{//构造函数
init();
}
void init()
{//对栈进行初始化
base = new T[16];//初始时,占用16个空间,这个可以自己设置,一般是2的n次方
listsize = 16;
length = 0;
top = base;
}
int enlarge()
{//当L的空间不足时,本函数功能:将L的空间翻倍
//如果成功返回1,失败返回0
T *newbase = new T[listsize * 2];//开辟新空间
if (0 == newbase)
return 0;
for (int i = 0; i<length; i++)//把老空间已有数据拷贝到新空间
newbase[i] = base[i];
delete[]base;//释放掉老空间,还给操作系统
base = newbase;//elem指向新空间首地址
listsize = listsize * 2;//空间大小翻倍
top = base + length;
return 1;
}
void push(T x)
{//入栈,即在顺序表尾部插入数据
if (length == listsize)
{//空间不足
enlarge();
}
*top = x;
top++;
length++;
}
void pop()
{//出栈,删除顺序表表尾元素
top--;
length--;
}
int size()
{//得到栈中元素个数
return length;
}
int isEmpty()
{//如果栈为空返回1,否则返回0
return length == 0;
}
T getTop()
{//得到栈顶元素
return *(top - 1);
}
void print()
{//测试用
T *p = base;
while (p < top)
{
cout << *p << " ";
p++;
}
cout << endl;
}
~stack()
{
delete[]base;
}
};
int main()
{
stack<int> s;
s.push(1);
s.push(3);
s.push(5);
s.print();
int x;
x = s.getTop();
cout << "the top of stack is:" << x << endl;
s.pop();
s.print();
s.pop();
s.print();
return 0;
}
三、链栈
用链表作为栈,在哪一头进行插入删除呢?
1、用单链表时,在头部插入和删除都方便。
2、用单向循环链表时,在头部插入和删除都方便;
3、用双向循环链表时,都比较方便。
因此,从复杂程度来看,用单链表实现栈,简单些。
#include "stdafx.h"
#include<iostream>
using namespace std;
//模板类,T是泛化类型
template<typename T>class stack
{//基于单链表的栈
struct node
{
T data;
node *next;
};
node *head;//头结点指针
int length;//实际元素的个数
public:
stack()
{//构造函数
init();
}
void init()
{//对栈进行初始化
head = new node;
head->next = 0;
length = 0;
}
void push(T x)
{//入栈,即在单链表头部插入数据
node *t;
t = new node;
t->data = x;
t->next = head->next;
head->next = t;
length++;
}
void pop()
{//出栈,删除单链表表头元素
node *t;
t = head->next;
head->next = t->next;
delete t;
length--;
}
int size()
{//得到栈中元素个数
return length;
}
int isEmpty()
{//如果栈为空返回1,否则返回0
return length == 0;
}
T getTop()
{//得到栈顶元素
node *t = head->next;
return t->data;
}
void print()
{//测试用
node *p = head->next;
while (p)
{
cout << p->data << " ";
p=p->next;
}
cout << endl;
}
~stack()
{
delete[]head;
}
};
int main()
{
stack<int> s;
s.push(1);
s.push(3);
s.push(5);
s.print();
int x;
x = s.getTop();
cout << "the top of stack is:" << x << endl;
s.pop();
s.print();
s.pop();
s.print();
return 0;
}
四、C++ STL的stack
在C++ STL中已经定义好了stack模板类。
以后我们直接用即可。
#include "stdafx.h"
#include<stack>//C++ STL 栈模板头文件
#include<iostream>
using namespace std;
template<typename T>
int main()
{
stack<int> s;//定义一个整数栈
int x;
s.push(1);//入栈
x = s.top();//得到栈顶元素
cout << "the top of stack is:" << x << endl;
s.push(3);
x = s.top();
cout << "the top of stack is:" << x << endl;
s.push(5);
x = s.top();
cout << "the top of stack is:" << x << endl;
s.pop();//出栈
x = s.top();
cout << "the top of stack is:" << x << endl;
s.pop();
x = s.top();
cout << "the top of stack is:" << x << endl;
return 0;
}
还有:s.size()得到栈中元素个数;
s.empty()判断栈是否为空;
由于其没有提供下标操作,因此想查看其中的所有元素,即遍历,就很复杂。
可以这样,把元素从栈中取出打印,存到另一个栈中,最后再恢复过去。
template<typename T>
void print(stack<T> &s)
{
stack<T> s2;
T x;
while (s.empty() == false)
{
x = s.top();
cout << x << " ";
s2.push(x);
s.pop();
}
cout << endl;
while (s2.empty() == false)
{
x = s2.top();
s2.pop();
s.push(x);
}
}