首先明确,栈和队列 是特殊的线性表。
栈(STL : STACK)
一、定义
栈是只能在一端进行插入和删除操作的线性表
日常例子:
洗碗摞一堆; 书摞成一堆; 一些枪支子弹夹中子弹的操作方式等。
1.1一些基本概念
栈顶(top) 进行插入和删除操作的一端
栈底(bottom) 相对栈顶的另一端
入栈(push) 插入操作
出栈(pop) 出栈操作
空栈:无元素的栈
1.2栈的特性
后进先出 ( LIFO-- Last In First Out ),或 先进后出 ( FILO-- First In Last Out )
二、顺序栈
2.1基本运算函数
#define MAXLEN 105
typedef struct { //结构体定义顺序栈
int data[MAXLEN];
int top;
}seqStack;
void initStack(seqStack *S) { //初始化栈,将栈顶置于-1,这样开始时从0插入
S->top = -1;
}
bool stackEmpty(seqStack &S){ //判断栈是否为空
if(S.top == -1) return true;
else return false;
//return(S->top==-1);
}
bool stackFull(seqStack *S) { //判断栈是否为满
if(S->top == MAXLEN - 1) return true;
else return false;
}
void stackTop(seqStack *S, int *x) { //X取为栈顶元素
if(S->top == -1) {cout << "EMPTY ERROR" <<endl;return;}
else *x = S->data[S->top];
}
void push(seqStack *S, int x) { //插入
if(S->top == MAXLEN - 1) {
cout <<"ERROR"<<endl;
return;
}else {
S->top++;
S->data[S->top] = x;
}
}
void pop(seqStack *S,int &x) { //弹栈同时取到弹出元素
if(stackEmpty(*S)) {cout <<"ERROR" <<endl; return;}
else {
x = S->data[S->top--];
}
}
2.2 顺序栈的特点
所有运算的时间复杂度均为O(1); 通常一次性申请空间,只能按最大空间需求分配,容易造成空间浪费。-- 使用链式栈。
三、链栈
(以下运算为不带头结点的运算)
typedef struct {
int data[MAXLEN];
int top;
}seqStack;
typedef struct listNode{
int data;
struct listNode *next;
}node;
void initStack_1(node *&top) {
top = NULL;
}
bool stackEmpty_1(node *top) {
return (top == NULL);
}
bool stackTop(node *top, int x) { //由于头插法top仅跟着栈顶
if(!top) return false;
else {
x = top -> data;
return true;
}
}
void push_1(node *& top, int x) { //头插
node *s;
s = new node;
s->data = x;
s->next = top;
top = s;
}
bool pop_1(node *& top, int &x) {
node *u;
if(!top) return false;
else {
x = top->data; //取弹出元素
u = top; //临时指针指到top
top = top->next; //top 后移
delete(u); //删除结点
return true;
}
}
void DeleteStack(node *&top) {
node *p, *u;
p = top;
while(p) {
u = p;
p = p->next;
delete(u);
}
top = NULL;
}
时间复杂度上,销毁链栈是O(N),其余均为O(1)
链栈的特点
·使用连续或不连续的储存空间
·各数据元素独立储存,依靠指针链接逻辑相邻关系
·对每个数据元素都单独申请结点
·不会存在栈满溢出的问题
·每个栈顶指针top唯一确定一个链栈
栈的应用举例
一、单链表的就地逆置
方法一、使用中间结点头插法建立新表
void reverse(node *&L) { //STACK APPLICATION-1
node *P = NULL; //P指向i-1
node *u; //u指向i
while(L) {
u = L; //u指向待分离的表头
L = L->next; //未逆置部分的表头指针L后移指向i+1
u->next = P; //新分离的i结点的next指向P 形成逆置
P = u; //已逆置部分的头指针P指向i
}
L = P; //原表头指针指向新表头
}
方法二、使用栈
将元素结点存在栈中,依次弹栈后用尾插法建立链表
void reverse1(node *&L) { //STACK APPLICATION-2
node *R, *u;
seqStack S;
initStack(&S);
u = L;
while(u) {
push(S,u); //结点压入栈
u = u->next;
}
if(stackEmpty(S)) {
return;
}
stackTop(&S,u); //取栈顶元素
L = u; //新的表头元素
R = u; //表尾指针
u->next = NULL;
pop(S,u);
while(!stackEmpty(S)) {
stackTop(S,u);
R->next = u;
u->next = NULL;
R = u;
pop(S,u);
}
}
逆波兰表达式
#include <iostream>
#include <stack>
using namespace std;
const int MAXN = 1000 + 5;
char s[MAXN];
int pos; //数组下标
int trans(int &pos) {
int ans = 0;
while(s[pos] >= '0' &&s[pos] <= '9') {
ans *= 10;
ans += (s[pos] -'0');
pos++;
}
return ans;
}
int Level(char ch) {
switch (ch) {
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
case '(':
return 0;
case '#':
return -1;
}
}
int Op(int a1, char op, int a2) {
switch (op) {
case '+':
return a1 + a2;
case '-':
return a1 - a2;
case '*':
return a1 * a2;
case '/':
return a1 / a2;
}
}
int Computer() {
stack<int> op1;
stack<char> op2;
op2.push('#');
int len = strlen(s);
bool minus = true;
for(pos = 0; pos < len;) {
if(s[pos] == '-' && minus) {
op1.push(0);
op2.push('-');
pos++;
}
else if (s[pos] == ')') {
minus = false;
pos++;
while(op2.top() != '(') {
int a2 = op1.top();
op1.pop();
int a1 = op1.top();
op1.pop();
char op = op2.top();
op2.pop();
int res = Op(a1,op,a2);
op1.push(res);
}
op2.pop();
}
else if(s[pos] >= '0' && s[pos] <= '9') {
minus = false;
op1.push(trans(pos));
}
else if (s[pos] == '(') {
minus = false;
op2.push(s[pos]);
pos++;
}
else {
while(Level(s[pos]) <= Level(op2.top())) {
int a2 = op1.top();
op1.pop();
int a1 = op1.top();
op1.pop();
char op = op2.top();
op2.pop();
int res = Op(a1,op,a2);
op1.push(res);
}
op2.push(s[pos]);
pos++;
}
}
while(op2.top()!='#') {
int a2 = op1.top();
op1.pop();
int a1 = op1.top();
op1.pop();
char op = op2.top();
op2.pop();
int res = Op(a1,op,a2);
op1.push(res);
}
return op1.top();
}
int main() {
cin >> s;
cout << "The Result is that:" << Computer() << endl;
return 0;
}