栈:是插入和删除只能在一端进行的线性表
例:线性表(a1...a5)进栈出栈示意图
栈的特点:有序性,先进后出,后进先出。栈指针永远指向栈顶。
向栈顶压如一个元素item,
if(top==MaxStackSize - 1){
//判断是否栈满
}
top++;//先修改指针,再插入元素
StackList[top] = item; // StackList是一个数组
从栈顶删除一个元素
if(top= -1 ){//如果栈顶指针为-1,则为空栈
// 判断是否为空
}
temp = StackList[top];//先将元素赋值给临时变量以便使用
top--;//然后栈顶指针向下移动
return temp;
读栈顶元素(只读不删不改)
先判断栈是否为空,然后 return StackList[top];
判断栈是否为空
return top == -1;//栈空
判断栈是否为满
return top == MaxStackSize - 1 ;//栈满
栈的应用--迷宫探索
Status Pass(MazeType MyMaze, PosType CurPos);
void FootPrint(MazeType &MyMaze, PosType CurPos);
void MarkPrint(MazeType &MyMaze, PosType CurPos);
PosType NextPos(PosType CurPos, int Dir);
Status MazePath(MazeType &maze, PosType start, PosType end) {
// 若迷宫maze中从入口 start到出口 end的通道,则求得一条存放在栈中
// (从栈底到栈顶),并返回TRUE;否则返回FALSE
Stack S;
PosType curpos;
int curstep;
SElemType e;
InitStack(S);
curpos = start; // 设定"当前位置"为"入口位置"
curstep = 1; // 探索第一步
do {
if (Pass(maze,curpos)) { // 当前位置可通过,即是未曾走到过的通道块
FootPrint(maze,curpos); // 留下足迹
e.di =1;
e.ord = curstep;
e.seat= curpos;
Push(S,e); // 加入路径
if (curpos.r == end.r && curpos.c==end.c)
return (TRUE); // 到达终点(出口)
curpos = NextPos(curpos, 1); // 下一位置是当前位置的东邻
curstep++; // 探索下一步
} else { // 当前位置不能通过
if (!StackEmpty(S)) {
Pop(S,e);
while (e.di==4 && !StackEmpty(S)) {
MarkPrint(maze,e.seat);
Pop(S,e); // 留下不能通过的标记,并退回一步
} // while
if (e.di<4) {
e.di++;
Push(S, e); // 换下一个方向探索
curpos = NextPos(e.seat, e.di); // 当前位置设为新方向的相邻块
} // if
} // if
} // else
} while (!StackEmpty(S) );
return FALSE;
} // MazePath
Status Pass( MazeType MyMaze,PosType CurPos) {
if (MyMaze.arr[CurPos.r][CurPos.c]==' ')
return 1; // 如果当前位置是可以通过,返回1
else return 0; // 其它情况返回0
}
void FootPrint(MazeType &MyMaze,PosType CurPos) {
MyMaze.arr[CurPos.r][CurPos.c]='*';
}
void MarkPrint(MazeType &MyMaze,PosType CurPos) {
MyMaze.arr[CurPos.r][CurPos.c]='!';
}
PosType NextPos(PosType CurPos, int Dir) {
PosType ReturnPos;
switch (Dir) {
case 1:
ReturnPos.r=CurPos.r;
ReturnPos.c=CurPos.c+1;
break;
case 2:
ReturnPos.r=CurPos.r+1;
ReturnPos.c=CurPos.c;
break;
case 3:
ReturnPos.r=CurPos.r;
ReturnPos.c=CurPos.c-1;
break;
case 4:
ReturnPos.r=CurPos.r-1;
ReturnPos.c=CurPos.c;
break;
}
return ReturnPos;
}
#define OPSETSIZE 7
unsigned char Prior[7][7] = {
'>','>','<','<','<','>','>',
'>','>','<','<','<','>','>',
'>','>','>','>','<','>','>',
'>','>','>','>','<','>','>',
'<','<','<','<','<','=',' ',
'>','>','>','>',' ','>','>',
'<','<','<','<','<',' ','='
};
float Operate(float a, unsigned char theta, float b);
char OPSET[OPSETSIZE]={'+' , '-' , '*' , '/' ,'(' , ')' , '#'};
Status In(char Test,char* TestOp);
char precede(char Aop, char Bop);
float EvaluateExpression(char* MyExpression) { // 算法3.4
// 算术表达式求值的算符优先算法。
// 设OPTR和OPND分别为运算符栈和运算数栈,OP为运算符集合。
StackChar OPTR; // 运算符栈,字符元素
StackFloat OPND; // 运算数栈,实数元素
char TempData[20];
float Data,a,b;
char theta,*c,x,Dr[2];
InitStack (OPTR);
Push (OPTR, '#');
InitStack (OPND);
c = MyExpression;
strcpy(TempData,"\0");
while (*c!= '#' || GetTop(OPTR)!= '#') {
if (!In(*c, OPSET)) {
Dr[0]=*c;
Dr[1]='\0';
strcat(TempData,Dr);
c++;
if(In(*c,OPSET)) {
Data=(float)atof(TempData);
Push(OPND, Data);
strcpy(TempData,"\0");
}
} else { // 不是运算符则进栈
switch (precede(GetTop(OPTR), *c)) {
case '<': // 栈顶元素优先权低
Push(OPTR, *c);
c++;
break;
case '=': // 脱括号并接收下一字符
Pop(OPTR, x);
c++;
break;
case '>': // 退栈并将运算结果入栈
Pop(OPTR, theta);
Pop(OPND, b);
Pop(OPND, a);
Push(OPND, Operate(a, theta, b));
break;
} // switch
}
} // while
return GetTop(OPND);
} // EvaluateExpression
float Operate(float a,unsigned char theta, float b) {
switch(theta) {
case '+': return a+b;
case '-': return a-b;
case '*': return a*b;
case '/': return a/b;
default : return 0;
}
}
Status In(char Test,char* TestOp) {
bool Find=false;
for (int i=0; i< OPSETSIZE; i++) {
if (Test == TestOp[i]) Find= true;
}
return Find;
}
int ReturnOpOrd(char op,char* TestOp) {
int i;
for(i=0; i< OPSETSIZE; i++) {
if (op == TestOp[i]) return i;
}
return 0;
}
char precede(char Aop, char Bop) {
return Prior[ReturnOpOrd(Aop,OPSET)][ReturnOpOrd(Bop,OPSET)];
}
当程序需要多个栈的时候--链式栈
将链表和栈联合使用,将top用数组进行使用。