数据结构 - 栈的基本操作+四则运算(后缀表达式)

数据结构 专栏收录该内容
7 篇文章 0 订阅

10月21日晨刷完之后更新
栈是特殊的线性表(数据具有前驱后继的关系)
然后栈的一个重要规则是后进先出,就是说他只能在表尾(栈顶)进行插入和删除的操作
老师上课的时候讲了一个例子,(据说有点重要)
例:对于元素1、2、3进行入栈和出栈操作,最多可得到?种不同的情况
回答:5种,图的话等我去ppt上截(就是不同的入栈和出栈次序改变拿到元素的情况)
具体形式
和线性表一样,实现栈这个数据结构也有两种方法,称之为顺序栈和链栈
单独拎出来讲,先顺序栈
用top表示栈顶元素的位置,
top=0表示栈内只有一个元素,top=-1表示空栈
定义
然后是进栈的操作
顺序栈进栈操作
然后是出栈的操作
顺序栈出栈操作
接下来讲链栈= =
栈内每个数据都有它的data域和next域就是数据域和指针域,看起来就会形成一个链的结构–>
链栈示意图
和顺序栈一样,定义和入栈+出栈:
通过上面的图就可以得到链栈的结构体形式,为了让结构更清晰,这里定义了两个结构体,一个表示链栈内的元素,另一个表示链栈本身 = =,还有一个属性是count
链栈的定义
入栈操作:
链栈的入栈操作
出栈操作:
链栈的出栈操作
完了讲一下顺序栈的优缺点)优点就是实现栈后进先出的原则,还有数据的插入和输出操作十分方便;缺点的话就是栈的大小是固定的= =很容易照成资源分配上的浪费

然后,讲到了栈的应用,like计算机实现三年级进行的四则运算。首先,百度一下得到其定义 — [四则运算是指加法、减法、乘法和除法四种运算。四则运算是小学数学的重要内容,也是学习其它各有关知识的基础。] 得到其表达式应该是’+’ ‘-’ ‘*’ ‘/’ ‘(’ ')'符合加上数组组成的一个字符串
如何计算得出结果呢。先乘除后加减,有括号先算括号……

很显然行不通

高级一点,我们需要把原来的表达式进行转化,将其变为后缀表达式,然后再利用栈对其进行运算得出结果= =
问:原来的表达式叫什么
回答:中缀表达式

问:后缀表达式是什么
回答:逆波兰式(Reverse Polish notation,RPN,或逆波兰记法),也叫后缀表达式(将运算符写在操作数之后)

问:如何得到后缀表达式
回答:从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于找顶符号(乘除优先加减)则栈顶元素依次出找并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。

问:能简单点吗
回答:可以~
中缀表达式转后缀表达式快速方法:将所有表达式括起来然后符号位放到右括号后面

举个栗子 (9+6)7-8/2 ==>> ( ( (9+6)7 ) - (8/2) ) ==>> (((96)+7)(82)/)- 括号去掉得到后缀表达式: 96+782/-

问:假设我们已经得到后缀表达式惹,如何计算
回答:从左到右扫描后缀表达式,如果遇到操作数,将其压入栈中,如果遇到操作符,则从栈中弹出两个操作数,计算结果,然后把结果入栈,直到遍历完后缀表达式,则计算完成,此时的栈顶元素即为计算结果

(问:有代码吗
回答:有的 ⬇ )


先贴代码再总结,明天还要晨刷所以先不bb惹
明天数据结构见……

#include <stdio.h>
#include <stdlib.h>
 
#define OK     1
#define ERROR  -1
struct node
{
	int data;
	struct node *next;
};
typedef struct node Node;
 
struct stack
{
	Node *top;
	int count;
};
typedef struct stack Stack;
 
int InitStack(Stack *l)
{
	l->top = NULL;
	l->count = 0;
 
	return OK;
}
 
int EmptyStack(Stack *s)
{
	return (s->count == 0) ? OK : ERROR;
}
 
int Push(Stack *s, int e)
{
	//……
}
 
int GetTop(Stack *s)
{
	//……
}
 
int Priority(char s)
{
	switch(s)
	{
		case '(':
			return 3;
		case '*':
		case '/':
			return 2;
		case '+':
		case '-':
			return 1;
		default:
			return 0;
	}
}
 
int Pop(Stack *s)
{
	//……
}
 
int main()
{
	Stack num, opt;
	char str[100]={0};
	int i = 0, tmp = 0, j;
	if(InitStack(&num) != OK || InitStack(&opt) != OK)
	{
		printf("Init Failure!\n");
		return 0;
	}
	printf("Please Input Operator :\n");
	scanf("%s",str);
	while(str[i] != '\0' || EmptyStack(&opt) != OK)
	{
		if(str[i] >= '0' && str[i] <= '9')
		{
			tmp = tmp * 10 + str[i] - '0';
			i++;
			if(str[i] < '0' || str[i] > '9')
			{
				Push(&num,tmp);
				tmp = 0;
			}
		}
		else
		{
			if((EmptyStack(&opt) == OK) || (GetTop(&opt) == '(' && str[i] != ')') || Priority(str[i]) > Priority(GetTop(&opt)))//进栈不参与运算
			{
				Push(&opt,str[i]);
				i++;
				continue;
			}
			if(GetTop(&opt) == '(' && str[i] == ')')
			{
				Pop(&opt);
				i++;
				continue;
			}
			if((str[i] == '\0' && EmptyStack(&opt) != OK) || (str[i] == ')' && GetTop(&opt) != '(') || Priority(str[i]) <= Priority(GetTop(&opt)))//出栈并参与运算
			{
				switch(Pop(&opt))
				{
					case '+':
						Push(&num, Pop(&num) + Pop(&num));
						break;
					case '-':
						j = Pop(&num);
						Push(&num, Pop(&num) - j);
						break;
					case '*':
						Push(&num, Pop(&num) * Pop(&num));
						break;
					case '/':
						j = Pop(&num);
						Push(&num, Pop(&num) / j);
				}
				continue;
			}
		}
	}
	printf("%d\n",Pop(&num));
        return 0;
}
  • 6
    点赞
  • 0
    评论
  • 17
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 终极编程指南 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值