数据结构与算法-栈与队列的应用递归表达式求值
参考学习:B站-逊哥带你学编程
栈与队列的应用
题1:
答案:B
题2:
答案:C
题3:
答案:D
题4:
答案:C
题5:
答案:B
题6:
答案: B
题7:
答案: C
题8:
答案:B
题9:
答案: C
题10:
答案:C
题11:
答案:B
题12:
答案:C
题13:
答案:D
题14:
答案:D
递归
非递归
int fun(int n) //非递归
{
int sum = 0;
for(int i=1; i<=n; i++)
{
sum += i;
}
return sum;
}
递归
//递归
int fun(int n)
{
if(n == 1)
{
return 1;
}
else
{
return n + fun(n-1); //递归调用
}
}
图示:
最终返回的值为15。
斐波那契数列
非递归方式:
int fibonacci(int n) //非递归
{
int last1 = 1;
int last2 = 1;
int result = 0;
for(int i=3; i<=n; i++)
{
result = last1 + last2; //计算第i个斐波那契数
last2 = last1; //更新last2
last1 = result; //更新last1
}
return result; //返回第n个斐波那契数
}
递归方式:
int fibonacci(int n) //递归
{
if(n == 1 || n == 2)
{
return 1;
}
else
{
return fibonacci(n-1) + fibonacci(n-2); //递归调用
}
}
表达式求值
枚举
后缀表达式求值
题目:
82/2+56*-
求值过程图示:
先把需要运算的数字入栈,遇到运算符之后,再出栈,先入栈的为操作数op1
,后入栈的为操作数op2
,运算完成后,再次入栈,计算剩余项,直到字符串表达式结束。
代码实现:
使用栈实现:
//后缀表达式求值
#define MAXSIZE 100
typedef int ElemType;
typrdef struct
{
ElemType *data;
int top;
}Stack;
typedef enum
{
LEFT_PARE, RIGHT_PARE,
ADD, SUB, MUL, DIV, MOD,
EOS, NUM
} contentType;
char expr[] = "82/2+56*-"; //后缀表达式
Stack *initStack()
{
Stack *S = (Stack *)malloc(sizeof(Stack));
S->data = (ElemType *)malloc(sizeof(ElemType)*MAXSIZE);
S->top = -1;
return S;
}
contentType getToken(char *symbol, int *index)
{
*symbol = expr[*index]; //取出一个字符
*index = *index + 1; //指针后移
switch(*symbol)
{
case '(': return LEFT_PARE;
case ')': return RIGHT_PARE;
case '+': return ADD;
case '-': return SUB;
case '*': return MUL;
case '/': return DIV;
case '%': return MOD;
case '\0': return EOS;
default: return NUM;
}
}
int eval(Stack *S)
{
char symbol; //存放字符
int op1, op2; //操作数
int index = 0; //指针
contentType token; //存放类型
token = getToken(&symbol, &index); //取出一个字符
ElemType result; //存放结果
while(token != EOS) //不是结束符
{
if(token == NUM) //是数字
{
push(S, symbol-'0'); //入栈
}
else //是运算符
{
pop(S, &op2); //取出第二个操作数
pop(S, &op1); //取出第一个操作数
switch(token)
{
case ADD: push(S, op1+op2); break; //加法
case SUB: push(S, op1-op2); break; //减法
case MUL: push(S, op1*op2); break; //乘法
case DIV: push(S, op1/op2); break; //除法
case MOD: push(S, op1%op2); break; //取模
default: break;
}
}
token = getToken(&symbol, &index); //继续取出一个字符
}
pop(S, &result); //取出结果
printf("result = %d\n", result); //输出结果
return 1;
}
中缀表达式转后缀表达式
中缀表达式:x/(i-j)\*y
→后缀表达式:xij-/y\*
.
步骤:
1、如果是操作数,直接输出。
2、如果是运算符,判断优先级(优先级见下图),如果优先级大于栈顶元素的优先级,压入栈中。
3、当左括号在栈外时,属于最高优先级,当左括号在栈里时,属于最低优先级。
4、如果是操作数,直接输出。
5、如果是运算符,判断优先级(优先级见下图),如果优先级大于栈顶元素的优先级,压入栈中。
6、如果是操作数,直接输出。
7、如果是右括号,且栈顶元素不是左括号,持续出栈并输出,直到栈顶为左括号出栈结束最后将左括号也出栈。
(1)-
符号出栈。
(2)(
出栈。
8、如果是运算符,判断优先级,如果优先级大于栈顶元素,压入栈中,否则将栈顶元素出栈输出,然后将当前运算符压入栈中。
(1)/
出栈。
(2)*
入栈。
9、如果是操作数,直接输出。
10、最后将栈中元素依次输出,完成转换。
运算符优先级
运算符优先级,数字越大,优先级越高。
代码实现:
#define MAXSIZE 100
typedef int ElemType;
typedef struct
{
ElemType *data;
int top;
}Stack;
typedef enum
{
LEFT_PARE, RIGHT_PARE,
ADD, SUB, MUL, DIV, MOD,
EOS, NUM
} contentType;
char expr[] = "x/(i-j)*y"; //中缀表达式
> 这里是引用
Stack *initStack()
{
Stack *S = (Stack *)malloc(sizeof(Stack));
S->data = (ElemType *)malloc(sizeof(ElemType)*MAXSIZE);
S->top = -1;
return S;
}
contentType getToken(char *symbol, int *index)
{
*symbol = expr[*index]; //取出一个字符
*index = *index + 1; //指针后移
switch(*symbol)
{
case '(': return LEFT_PARE;
case ')': return RIGHT_PARE;
case '+': return ADD;
case '-': return SUB;
case '*': return MUL;
case '/': return DIV;
case '%': return MOD;
case '\0': return EOS;
default: return NUM;
}
}
int print_token(contentType token)
{
switch(token)
{
case LEFT_PARE: printf("("); break;
case RIGHT_PARE: printf(")"); break;
case ADD: printf("+"); break;
case SUB: printf("-"); break;
case MUL: printf("*"); break;
case DIV: printf("/"); break;
case MOD: printf("%"); break;
case EOS: printf("\n"); break;
default: break;
}
return 1;
}
void postfix(Stack *S)
{
int in_stack[] = {0, 19, 12, 12, 13, 13, 13, 0}; //栈内优先级
int out_stack[] = {20, 19, 12, 12, 13, 13, 13, 0}; //栈外优先级
contentType token; //存放类型
int index = 0; //指针
S->data[0] = EOS; //栈底放结束符
char symbol; //存放字符
ElemType e; //存放栈顶元素
token = getToken(&symbol, &index); //取出一个字符
while(token != EOS) //不是结束符
{
if(token == NUM) //是数字
{
printf("%c", symbol); //输出
}
else if(token == RIGHT_PARE) //是右括号
{
while(getTop(S, &e) && e != LEFT_PARE) //取出栈顶元素
{
pop(S, &e); //出栈
print_token(e); //输出
}
pop(S, &e); //出栈
}
else //是运算符
{
while(in_stack[S->data[S->top]] >= out_stack[token]) //取出栈顶元素
{
pop(S, &e); //出栈
print_token(e); //输出
}
push(S, token); //入栈
}
token = getToken(&symbol, &index); //继续取出一个字符
}
}