顺序栈的基本实现及应用
- 数制转换
//数制转换(十进制转八进制)
int conversion(int num)
{
//对于输入的任意一个非负十进制整数,打印输出与其等值的八进制数
SqStack<int> s;
int e = 0;
int result = 0;
while(num)
{
s.Push(num % 8);
num /= 8;
}
while(s.IsEmpty() != EMPTY)
{
s.Pop(e);
result = result*10 + e;
}
return result;
}
将取模后的数逐个入栈,再逐个出栈。
- 表达式求值
中缀表达式求值
创建两个栈,一个保存符号,一个保存数据。
//判断优先级
char Precede(char o1, char o2)
{
char f=' ';
switch(o2)
{
case '+':
case '-':
if(o1 == '(' || o1 == '#') //栈中符号优先级低
{
f = '<';
}
else
{
f = '>';
}
break;
case '*':
case '/':
if(o1=='*' || o1=='/' || o1==')')
{
f = '>';
}
else
{
f = '<';
}
break;
case '(':
if(o1 == ')')
{
cout<< "括号匹配错误!"<<endl;
exit(ERROR);
}
else
{
f = '<';
}
break;
case ')':
switch(o1)
{
case '(':
f = '='; //括号匹配
break;
case '#':
cout<< "输入了错误的括号!~"<<endl;
exit(ERROR);
default:
f = '>'; //其他情况站定元素的优先级更大
}
break;
case '#':
switch(o1)
{
case '#':
f = '=';
break;
case '(':
cout<< "表达式中有多余的括号!!"<<endl;
exit(ERROR);
default:
f = '>';
}
}
return f;
}
//运算函数
int Operate(int a, char theta, int b)
{
switch(theta)
{
case '+':
return a+b;
break;
case '-':
return a-b;
break;
case '*':
return a*b;
break;
case '/':
return a/b;
break;
}
return 0;
}
int EvalExpr(char *ptr)
{
SqStack<char> OPTR; //操作符栈
OPTR.Push('#'); //表达式起始符为'#'
SqStack<int> OPND; //操作数栈
char op, c, theta=' ', x, m;
int a=0, b=0;
c = *ptr++; //每一个数当做字符取出,ptr遍历后移
OPTR.GetTop(op);
while(c != '#' || op != '#')
{
if(!In(c)) //如果是数字直接进栈
{
m = atoi(&c); //将字符转化为数字
OPND.Push(m); //数字入栈
c = *ptr++; //指针后移
}
else //如果是符号的话,则先将这个符号与栈顶符号进行比较
{
switch(Precede(op, c))
{
case '<': //栈中符号优先级低,继续进栈
OPTR.Push(c);
c = *ptr++;
break;
case '=': //优先级相等时,说明遇到括号,需要托括号
OPTR.Pop(x); //脱括号
c = *ptr++;
break;
case '>': //栈中符号优先级高时,先计算,再将结果压入栈中
OPTR.Pop(theta); //运算符
OPND.Pop(b); //操作数
OPND.Pop(a);
OPND.Push(Operate(a, theta, b)); //将新的运算结果插到栈中
break;
}
}
OPTR.GetTop(op); //每一次更新当前栈顶符号
}
OPND.GetTop(a); //计算结果
return a;
}
后缀表达式求值
转换后的后缀式中没有括号
转换的过程真的是很核心所在,调试了半天
忽视了可以一次性出多个元素的情况— (+ * -> -)
减号进去时 *
和+
都得出来
//将中缀式转化为后缀式
char *change(char *ptr)
{
char *result = new char;
int i = 0;
SqStack<char> OPTR;
OPTR.Push('#');
char e=' ', op=' ';
while(*ptr != '#')
{
if(!In(*ptr))
{
*(result+i++) = *ptr;
}
else
{
if(*ptr == '(') //左括号直接进栈
{
OPTR.Push(*ptr);
}
else if(*ptr == ')') //右括号出到左括号为止
{
do{
OPTR.Pop(e);
if(e != '(')
*(result+i++) = e; //将不为左括号的元素进栈
}while(e != '(');
}
else
{
OPTR.GetTop(op);
switch(Precede(op, *ptr))
{
case '<':
OPTR.Push(*ptr);
break;
case '=':
case '>':
do{
OPTR.Pop(e);
*(result+i++) = e;
OPTR.GetTop(op);
}while(Precede(op, *ptr) == '>'); //有可能出现多个优先的情况(+* -)
//+和*号必须都出去
OPTR.Push(*ptr);
}
}
}// end of else
ptr++;
}// end of while
while(OPTR.IsEmpty() != EMPTY)
{
OPTR.Pop(e);
if(e != '#')
*(result+i++) = e;
}
*(result+i) = '\0';
return result;
}
//后缀表达式求值
int EvalExpr_RPN(char *exp)
{
SqStack<int> s;
int a=0, b=0, e=0;
while(*exp != '\0') //没有读取到字符串尾部
{
if(!In(*exp)) //读取的字符是数字不是符号
{
s.Push(*exp-48); //字符转数字‘1’->1;数字直接入栈
}
else
{
s.Pop(b);
s.Pop(a);
s.Push(Operate(a, *exp, b)); //弹出两个数进行运算
}
exp++; //z指针后移
}
s.Pop(e); //计算结果为e
return e;
}
- 递归
经典例子: Fibonacci数列
int Fib(n)
{
if(n < 1)
{
return 0;
}
else if(n <= 2)
{
return 1;
}
else
{
return Fib(n-1)+Fib(n-2);
}
}
- 斐波那契数列的一般实现 --迭代
#include <cstdio>
int main()
{
int a[20];
printf("迭代显示斐波那契数列:\n");
a[0] = 0;
a[1] = 1;
printf("%d ", a[0]);
printf("%d ", a[1]);
for(int i=2; i<20; i++)
{
a[i] = a[i-1] + a[i-2];
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
- 斐波那契数列递归实现
#include <cstdio>
int Fbi(int i) //斐波那契递归函数
{
if(i < 2)
{
return i == 0?0:1;
}
return Fbi(i-1)+ Fbi(i-2);
}
int main()
{
printf("递归显示斐波那契数列:\n");
for(int i=0; i<20; i++)
{
printf("%d ", Fbi(i));
}
printf("\n");
return 0;
}
扫描二维码关注公众号,回复:
3447811 查看本文章
完整源码
#include <iostream>
#include <cstdlib>
using namespace std;
const int STACK_INIT_SIZE = 20;
const int ERROR = 0;
const int OK = 1;
const int EMPTY = 0;
typedef int Status;
template <class T>
class SqStack
{
public:
SqStack();
~SqStack();
Status Push(T e);
Status Pop(T &e);
Status GetTop(T &e) const;
int StackLength() const;
Status IsEmpty();
void DispStack();
private:
T *base;
T *top; //栈顶指针
int stacksize;
};
//初始化一个栈
template <class T>
SqStack<T>::SqStack()
{
base = new T[STACK_INIT_SIZE];
top = base;
stacksize = STACK_INIT_SIZE;
}
//释放一个栈
template <class T>
SqStack<T>::~SqStack()
{
delete[] base;
}
//取顺序栈栈顶元素算法
template <class T>
Status SqStack<T>::GetTop(T &e) const
{
if(top == base)
{
return ERROR;
}
e = *(top-1);
return OK;
}
//顺序栈入栈
template <class T>
Status SqStack<T>::Push(T e)
{
if(top - base >= stacksize)
{
return ERROR;
}
*top++ = e; //先赋值,再加指针
return OK;
}
//顺序栈出栈
template <class T>
Status SqStack<T>::Pop(T &e)
{
if(top == base)
{
return ERROR;
}
e = *--top; //先减指针,再取值
return OK;
}
template <class T>
int SqStack<T>::StackLength() const
{
int sizeCount =0;
T *p = top-1;
while(p >= base)
{
sizeCount++;
p--;
}
return sizeCount;
}
template <class T>
Status SqStack<T>::IsEmpty() //空栈为0,非空栈为1;
{
if(top == base)
{
return EMPTY;
}
else
{
return OK;
}
}
template <class T>
void SqStack<T>::DispStack()
{
T *p = top-1;
while(p >= base)
{
cout<< *p << " ";
p--;
}
cout<< endl;
}
bool In(char c)
{
if(c>48 && c<57)
{
return false;
}
else
{
return true;
}
}
//数制转换(十进制转八进制)
int conversion(int num)
{
//碎玉输入的任意一个非负十进制整数,打印输出与其等值的八进制数
SqStack<int> s;
int e = 0;
int result = 0;
while(num)
{
s.Push(num % 8);
num /= 8;
}
while(s.IsEmpty() != EMPTY)
{
s.Pop(e);
result = result*10 + e;
}
return result;
}
//判断优先级
char Precede(char o1, char o2)
{
char f=' ';
switch(o2)
{
case '+':
case '-':
if(o1 == '(' || o1 == '#') //栈中符号优先级低
{
f = '<';
}
else
{
f = '>';
}
break;
case '*':
case '/':
if(o1=='*' || o1=='/' || o1==')')
{
f = '>';
}
else
{
f = '<';
}
break;
case '(':
if(o1 == ')')
{
cout<< "括号匹配错误!"<<endl;
exit(ERROR);
}
else
{
f = '<';
}
break;
case ')':
switch(o1)
{
case '(':
f = '='; //括号匹配
break;
case '#':
cout<< "输入了错误的括号!~"<<endl;
exit(ERROR);
default:
f = '>'; //其他情况站定元素的优先级更大
}
break;
case '#':
switch(o1)
{
case '#':
f = '=';
break;
case '(':
cout<< "表达式中有多余的括号!!"<<endl;
exit(ERROR);
default:
f = '>';
}
}
return f;
}
//运算函数
int Operate(int a, char theta, int b)
{
switch(theta)
{
case '+':
return a+b;
break;
case '-':
return a-b;
break;
case '*':
return a*b;
break;
case '/':
return a/b;
break;
}
return 0;
}
int EvalExpr(char *ptr)
{
SqStack<char> OPTR; //操作符栈
OPTR.Push('#'); //表达式起始符为'#'
SqStack<int> OPND; //操作数栈
char op, c, theta=' ', x, m;
int a=0; //操作数a
int b=0; //操作数b
c = *ptr++; //每一个数当做字符取出,ptr遍历后移
OPTR.GetTop(op);
while(c != '#' || op != '#')
{
if(!In(c)) //如果是数字直接进栈
{
m = atoi(&c); //将字符转化为数字
OPND.Push(m); //数字入栈
c = *ptr++; //指针后移
}
else //如果是符号的话,则先将这个符号与栈顶符号进行比较
{
switch(Precede(op, c))
{
case '<': //栈中符号优先级低,继续进栈
OPTR.Push(c);
c = *ptr++;
break;
case '=': //优先级相等时,说明遇到括号,需要托括号
OPTR.Pop(x); //脱括号
c = *ptr++;
break;
case '>': //栈中符号优先级高时,先计算,再将结果压入栈中
OPTR.Pop(theta); //运算符
OPND.Pop(b); //操作数
OPND.Pop(a);
OPND.Push(Operate(a, theta, b)); //将新的运算结果插到栈中
break;
}
}
OPTR.GetTop(op); //每一次更新当前栈顶符号
}
OPND.GetTop(a); //计算结果
return a;
}
//将中缀式转化为后缀式
char *change(char *ptr)
{
char *result = new char;
int i = 0;
SqStack<char> OPTR;
OPTR.Push('#');
char e=' ', op=' ';
while(*ptr != '#')
{
if(!In(*ptr))
{
*(result+i++) = *ptr;
}
else
{
if(*ptr == '(') //左括号直接进栈
{
OPTR.Push(*ptr);
}
else if(*ptr == ')') //右括号出到左括号为止
{
do{
OPTR.Pop(e);
if(e != '(')
*(result+i++) = e; //将不为左括号的元素进栈
}while(e != '(');
}
else
{
OPTR.GetTop(op);
switch(Precede(op, *ptr))
{
case '<':
OPTR.Push(*ptr);
break;
case '=':
case '>':
do{
OPTR.Pop(e);
*(result+i++) = e;
OPTR.GetTop(op);
}while(Precede(op, *ptr) == '>'); //有可能出现多个优先的情况(+* -)
//+和*号必须都出去
OPTR.Push(*ptr);
}
}
}// end of else
ptr++;
}// end of while
while(OPTR.IsEmpty() != EMPTY)
{
OPTR.Pop(e);
if(e != '#')
*(result+i++) = e;
}
*(result+i) = '\0';
return result;
}
//后缀表达式求值
int EvalExpr_RPN(char *exp)
{
SqStack<int> s;
int a=0, b=0, e=0;
while(*exp != '\0') //没有读取到字符串尾部
{
if(!In(*exp)) //读取的字符是数字不是符号
{
s.Push(*exp-48); //字符转数字‘1’->1;数字直接入栈
}
else
{
s.Pop(b);
s.Pop(a);
s.Push(Operate(a, *exp, b)); //弹出两个数进行运算
}
exp++; //z指针后移
}
s.Pop(e); //计算结果为e
return e;
}
int main()
{
SqStack<int> stack1;
for(int i=0; i<10; i++)
{
stack1.Push(i);
}
stack1.DispStack();
cout<< stack1.StackLength()<< endl;
int temp = 0;
stack1.GetTop(temp);
cout<< "temp = " << temp<< endl;
cout << stack1.IsEmpty() << endl;
stack1.Push(10);
stack1.DispStack();
cout <<stack1.Pop(temp)<< endl;
cout<< temp<<endl;
stack1.DispStack();
cout << "****************" << endl;
cout << "请输入一个整数:";
int num = 0;
cin >> num;
cout << num << "对应的八进制数为:" << conversion(num) <<endl;
char a[17] = "1+2*(5-3)-6/2+4#";
char *exp = a;
int opnd = EvalExpr(exp);
cout<< "作为示例 " << exp << "的计算结果为 " << opnd <<endl;
cout << exp << "转化为后缀表达式为" << change(exp) <<endl;
cout << "后缀表达式求值为" << EvalExpr_RPN(change(exp)) <<endl;
return 0;
}
运行结果