栈的应用
因为原本写栈的时候并没有用泛型编程,做到迷宫的时候必须用泛型,所以临时改成泛型,导致有点乱,这些应用很多可以不必用泛型的地方也直接顺势改成了泛型
栈的实现:
https://blog.csdn.net/oowadanoko/article/details/109429297
数制转换
将十进制数与目标进制取余数,若结果大于10,还需将其转换为对应的字母(例:10转化为A,11转化为B),这样就可以转化为进制大于10的数,然后将结果都以字符形式存储与输出
语言有点混乱,直接看源码
template<typename ElemType>
Status conversion(int num, int scale, SqStack<ElemType>& S)//num为要转换的10进制数 scale为进制 S用来接收结果
{
int tem;
clear(S);//清空栈
if (scale <= 0)
{
cout << "进制不能小于0" << endl;
return ERROR;
}
while (num)
{
tem = num % scale;
if (tem < 10)//进制小于10
{
tem = tem + '0';//转化为字符ASCII码
push(S, tem);
}
else//进制大于10
{
tem = tem - 10 + 'A';
push(S, tem);
}
num /= scale;
}
return OK;
}
template<typename ElemType>
Status printCharTop2Base(SqStack<ElemType>& S)//按栈顶到栈底格式输出字符
{
for (int i = S.top - 1; i >= S.base; i--)
cout << (char)S.et[i];//转化为字符输出
cout << endl;
return OK;
}
void shuZhiZhuanHuan()
{
SqStack<int> S;
initSqStsck(S);
int num, scale;
cout << "输入要转换的10进制数:";
cin >> num;
cout << "输入进制:";
cin >> scale;
conversion(num, scale, S);
cout << "结果为:";
printCharTop2Base(S);
system("pause");
}
结果:
括号匹配
若输入非括号则无视,左括号则进栈,右括号则取栈顶元素,若是与之匹配的左括号则将栈顶元素出栈,继续匹配,否则即为匹配失败
template<typename ElemType>
bool isMatched(SqStack<ElemType>& S, char ch)//判断匹配
{
int e;
if (ch == '(' || ch == '[')
push(S, (int)ch);
if (ch == ')')
{
getTop(S, e);
if (e == '(')
pop(S, e);
else
return false;
}
if (ch == ']')
{
getTop(S, e);
if (e == '[')
pop(S, e);
else
return false;
}
return true;
}
void kuoHaoPiPei()
{
char ch;
bool flag = true;
SqStack<int> S;
initSqStsck(S);
cout << "输入内容:" << endl;
ch = getchar();
while (ch != EOF)
{
if (!isMatched(S, ch))
flag = false;
ch = getchar();
}
if (flag)
cout << "括号匹配" << endl;
else
cout << "括号不匹配" << endl;
system("pause");
}
结果:
行编辑程序
读取一个字符,若为其他字符则进栈,若为 ‘#’ 则出栈一个元素,若为 ‘@’ 则清空栈,直到读取到 ’\n’ 表示一行结束,输出栈,然后读取下一行的元素,重复以上步骤直到读取到EOF
template<typename ElemType>
Status printCharBase2Top(SqStack<ElemType>& S)//按栈底到栈顶格式输出字符
{
for (int i = S.base; i < S.top; i++)
cout << (char)S.et[i];//转化为字符输出
cout << endl;
return OK;
}
void hangBianJi()
{
SqStack<int> S, T, R;//T用于中继,R用于存放结果
initSqStsck(S);
initSqStsck(T);
initSqStsck(R);
char ch;
int i = 0;
int e;
cout << "输入内容:" << endl;
ch = getchar();//吃上一个操作的回车
ch = getchar();
while (ch != EOF)
{
while (ch != '\n' && ch != EOF)//判断一行
{
switch (ch)
{
case '#':
pop(S, e);
break;
case '@':
clear(S);
break;
default:
push(S, (int)ch);
break;
}
ch = getchar();
}
while (!isEmpty(S))//将S中的内容放入T中,顺序相反
{
pop(S, e);
push(T, e);
}
while (!isEmpty(T))//将T中的内容放入R中,顺序恢复
{
pop(T, e);
push(R, e);
}
push(R, (int)'\n');//一行结束,存放'\n',便于输出时保持格式
clear(S);
clear(T);
if (ch != EOF)//若不是文件结束则继续下一行
ch = getchar();
}
cout << "结果为:" << endl;
printCharBase2Top(R);
system("pause");
}
结果:
表达式求值
依次读取字符
若不为运算符则进入运算数栈并读取下一个数据;
若为运算符则和运算符栈栈顶元素比较优先级;
- 若栈顶元素优先级低则直接入栈该运算符并读取下一个数据;
- 若两个优先级相等则只能是一对括号,弹出栈顶的括号并读取下一个数据;
- 若栈顶元素优先级高则出栈,并出栈两个运算数进行相应计算,将运算结果入运算数栈,然后继续比较当前读取的运算符和运算符栈栈顶的元素的优先级
需注意该应用只能进行10以内的运算
语文不好 还是看源码吧
char OP[7] = { '+','-','*','/','(',')','#' };
char compare[7][7] =
{
'>','>','<','<','<','>','>',
'>','>','<','<','<','>','>',
'>','>','>','>','<','>','>',
'>','>','>','>','<','>','>',
'<','<','<','<','<','=',' ',
'>','>','>','>',' ','>','>',
'<','<','<','<','<',' ','='
};
bool isIn(char ch, char* OP)//判断是否为运算符
{
for (int i = 0; i < 7; i++)
{
if (ch == OP[i])
return true;
}
return false;
}
char precede(char e, char ch)//寻找优先级
{
int i, j;
i = j = 0;
while (true)//寻找横坐标
{
if (e == OP[i])
break;
i++;
}
while (true)//寻找纵坐标
{
if (ch == OP[j])
break;
j++;
}
return compare[i][j];
}
int calculate(int numa, char optr, int numb)//计算
{
int result = 0;
switch (optr)
{
case '+':
result = numa + numb;
break;
case '-':
result = numa - numb;
break;
case '*':
result = numa * numb;
break;
case '/':
result = numa / numb;
break;
}
return result;
}
void biaoDaShiQiuZhi()
{
char ch;
int e, numa, numb, optr;
SqStack<int> OPTR, OPND;
initSqStsck(OPTR);
initSqStsck(OPND);
push(OPTR, (int)'#');
cout << "输入表达式" << endl;
ch = getchar();//吃掉上一个操作的回车
ch = getchar();
while (ch != '#' || (getTop(OPTR, e), e != '#'))
{
if (!isIn(ch, OP))//不在OP中,即不是运算符
{
push(OPND, ch - '0');
ch = getchar();
}
else//是运算符
{
getTop(OPTR, e);
switch (precede(e, ch))//比较OPTR栈顶元素与ch的优先级
{
case '<'://OPTR优先级小,ch直接入栈
push(OPTR, (int)ch);
ch = getchar();
break;
case '='://优先级相等,表示左右括号相遇,直接出栈
pop(OPTR, e);
ch = getchar();
break;
case '>'://OPTR栈顶优先级大,需先进行计算,计算结果入栈
pop(OPND, numb);//注意此时栈顶的元素应该后算
pop(OPND, numa);
pop(OPTR, optr);
push(OPND, calculate(numa, optr, numb));
break;
default:
cout << "表达式非法" << endl;
break;
}
}
}
getTop(OPND, e);
cout << "结果为:" << e << endl;
system("pause");
}
结果:
迷宫求解
先将地图中未走过的地方标志为NO。首先将起点入栈,然后开始按上右下左的顺序寻找下一步,每次移动时都将自身的位置入栈,若自身的位置不是终点则继续按顺序寻找下一步,每次走下一步时都将该位置的值改为下一步移动的方向,若四个方向都无法移动则表示这条路是错的,出栈此位置,取得上一步的位置,继续走,直到到达终点。若栈空,则表示起点也出栈,意味着起点的四个方向均走不通,代表无解。
enum Direction
{
NO = 0,
UP = 1,
RIGHT = 2,
DOWN = 3,
LEFT = 4
};
int initMap[10][10] =
{
{8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
{8, 0, 0, 8, 0, 0, 0, 8, 0, 8},
{8, 0, 0, 8, 0, 0, 0, 8, 0, 8},
{8, 0, 0, 0, 0, 8, 8, 0, 0, 8},
{8, 0, 8, 8, 8, 0, 0, 0, 0, 8},
{8, 0, 0, 0, 8, 0, 0, 0, 0, 8},
{8, 0, 8, 0, 0, 0, 8, 0, 0, 8},
{8, 0, 8, 8, 8, 0, 8, 8, 0, 8},
{8, 8, 0, 0, 0, 0, 0, 0, 0, 8},
{8, 8, 8, 8, 8, 8, 8, 8, 8, 8}
};
Position initStartPos = { 1, 1 };
Position initEndPos = { 8, 8 };
int map[10][10];
void printAnswer(SqStack<Position> S)//输出答案
{
SqStack<Position> SS;
Position curPos;
initSqStsck(SS);
while (!isEmpty(S))
{
pop(S, curPos);
push(SS, curPos);
}
pop(SS, curPos);
cout << "(" << curPos.x << ", " << curPos.y << ")";
while (!isEmpty(SS))
{
pop(SS, curPos);
cout << " -- > (" << curPos.x << ", " << curPos.y << ")";
}
cout << endl;
}
bool isSamePosition(Position pa, Position pb)//判断两个点相同
{
return pa.x == pb.x && pa.y == pb.y;
}
bool nextPosition(Position curPos, Position& nextPos)//寻找下一个位置 nextPos用于存放结果
{
if (map[curPos.x][curPos.y] == NO && map[curPos.x - 1][curPos.y] == NO)//没来过当前位置且上方未去过或不是墙
{
nextPos.x = curPos.x - 1;
nextPos.y = curPos.y;
map[curPos.x][curPos.y] = UP;//说明这一步向上走
return true;
}
if (map[curPos.x][curPos.y] <= UP && map[curPos.x][curPos.y + 1] == NO)//上一次来时向上走或前面的方向走不通,且右方未去过或不是墙
{
nextPos.x = curPos.x;
nextPos.y = curPos.y + 1;
map[curPos.x][curPos.y] = RIGHT;//说明这一步向右走
return true;
}
if (map[curPos.x][curPos.y] <= RIGHT && map[curPos.x + 1][curPos.y] == NO)//上一次来时向右走或前面的方向走不通,且下方未去过或不是墙
{
nextPos.x = curPos.x + 1;
nextPos.y = curPos.y;
map[curPos.x][curPos.y] = DOWN;//说明这一步向下走
return true;
}
if (map[curPos.x][curPos.y] <= DOWN && map[curPos.x][curPos.y - 1] == NO)//上一次来时向下走或前面的方向走不通,且左方未去过或不是墙
{
nextPos.x = curPos.x;
nextPos.y = curPos.y - 1;
map[curPos.x][curPos.y] = LEFT;//说明这一步向左走
return true;
}
map[curPos.x][curPos.y] = LEFT;//四个方向均走不通,相当于已探索完四个方向且均无法走通
return false;
}
void miGongQiuJie()
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
map[i][j] = initMap[i][j];//恢复原地图,防止调用一次该函数后map的值被修改
cout << map[i][j] << " ";//输出原地图
}
cout << endl;
}
bool isFound = false;
SqStack<Position> S;
initSqStsck(S);
Position startPos = initStartPos;//起点
Position endPos = initEndPos;//终点
Position curPos = startPos;//当前位置
Position nextPos;//下一步
push<Position>(S, startPos);//起点入栈
while (true)
{
if (nextPosition(curPos, nextPos))//找到下一步
{
curPos = nextPos;//走到下一步,当前位置变为下一步
push(S, curPos);//当前位置入栈
if (isSamePosition(endPos, curPos))//如果当前位置在终点
{
isFound = true;
break;
}
}
else//找不到下一步
{
pop(S, curPos);//当前位置走不通,出栈
getTop(S, curPos);//回到上一步
}
if (isEmpty(S))//起点四个方向都走不通,被弹出栈,无解
{
break;
}
}
if (isFound)
{
printAnswer(S);
}
else
{
cout << "无解" << endl;
}
for (int i = 0; i < 10; i++)//查看地图
{
for (int j = 0; j < 10; j++)
cout << map[i][j] << " ";
cout << endl;
}
system("pause");
}
结果: