首先明確,棧和隊列 是特殊的線性表。
棧(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;
}