10黑马笔记之栈的应用_根据后缀表达式求解
1 前提:
1)如果是数字,直接进栈。
2)如果是运算符,依次从栈中取右操作数和左操作数进行运算,运算结果放回栈中,直至栈中剩下最后一个数字。
以上个例子求出的后缀表达式为例str = “831-5*+”,831进栈,减号取两操作数31运算结果为2,放回栈中,此时栈中有8和2。5进栈, 乘号运算2和5结果为10放回去。加号运算8和10也放回去,最终栈中只有18。最后弹出并输出就可以。
也是利用链式栈实现。
2 头文件:
#ifndef SEQLINKSTACK
#define SEQLINKSTACK
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//使用企业链表实现,也可传统
typedef struct LINKSNODE{
struct LINKSNODE *next;
}LinkSNode;
//管理链表结构体
typedef struct LINKSTACK{
LinkSNode head;
int size;
}LinkStack;
//链式栈初始化
LinkStack* Init_LinkStack();
//入栈
int Push_LinkStack(LinkStack *lstack,LinkSNode *data);
//出栈
int Pop_LinkStack(LinkStack *lstack);
//判断是否为空
int IsEmpty_LinkStack(LinkStack *lstack);
//返回第一个有效元素
LinkSNode *Top_LinkStack(LinkStack *lstack);
//返回栈大小
int Size_LinkStack(LinkStack *lstack);
//清空链式栈
int Clear_LinkStack(LinkStack *lstack);
//释放内存
int Destory_LinkStack(LinkStack *lstack);
#endif
3 栈的实现:
#include"Seq_LinkStack.h"
//链式栈初始化 ok
LinkStack* Init_LinkStack(){
LinkStack *lstack=(LinkStack*)malloc(sizeof(LinkStack));
lstack->head.next=NULL;
lstack->size=0;
return lstack;
}
//入栈 ok
int Push_LinkStack(LinkStack *lstack,LinkSNode *data){
if(lstack==NULL){
return -1;
}
if(data==NULL){
return -1;
}
//每次都在链表的头结点插入,与顺序栈想反
//所以每次对头结点操作插入
data->next =lstack->head.next;
lstack->head.next=data;
lstack->size++;
return 0;
}
//出栈 ok
int Pop_LinkStack(LinkStack *lstack){
if(lstack==NULL){
return -1;
}
if(lstack->size==0){
return -1;
}
//也是只对头结点操作
//使头结点指向第二个有效节点
LinkSNode *first=lstack->head.next;
lstack->head.next=first->next; //使head指向第二个元素
lstack->size--;
return 0;
}
//判断是否为空
int IsEmpty_LinkStack(LinkStack *lstack){
if(lstack==NULL){
return -1;
}
if(lstack->size==0){
return 1;
}
return 0;
}
//返回第一个有效元素 ok
LinkSNode *Top_LinkStack(LinkStack *lstack){
if(lstack==NULL){
return NULL;
}
if(lstack->size==0){
return NULL;
}
return lstack->head.next;
}
//返回栈大小 ok
int Size_LinkStack(LinkStack *lstack){
if(lstack==NULL){
return -1;
}
return lstack->size;
}
//清空链式栈 ok
int Clear_LinkStack(LinkStack *lstack){
if(lstack==NULL){
return -1;
}
//lstack->head.next=NULL;
lstack->size=0;
return 0;
}
//释放内存
int Destory_LinkStack(LinkStack *lstack){
if(lstack==NULL){
return -1;
}
free(lstack);
return 0;
}
4 主要逻辑代码:
#include"Seq_LinkStack.h"
#include<stdio.h>
//判断是否为数字
int IsNumber(char p) {
return p >= '0'&&p <= '9';
}
//判断是否为运算符
int IsOperator(char p) {
return p == '+' || p == '-' || p == '*' || p == '/';
}
//运算
int MyOperate(char op, int p1, int p2) {
if (op == '+'){
return p1 + p2;
}
if (op=='-') {
return p1 - p2;
}
if (op=='*') {
return (p1)*(p2);
}
if ('/') {
return (p1)/(p2);
}
return 0;
}
//数据节点
typedef struct MYCHAR {
LinkSNode node; //挂钩
int val;
}Mychar;
void test01() {
char *str = "831-5*+";
char *p = str;
//创建栈
LinkStack *stack = Init_LinkStack();
//遍历整个字符串
while (*p != 0) {
//1如果是数字 直接进栈
if (IsNumber(*p)) {
Mychar *myc = (Mychar*)malloc(sizeof(Mychar));
myc->val = *p - '0';
Push_LinkStack(stack, (LinkSNode*)myc);
}
//2如果是运算符 依次从栈中取右操作数和左操作数进行运算 运算结果放回栈中 直至栈中剩下最后一个数字
if (IsOperator(*p)) {
//获取右操作数
Mychar *tmp = (Mychar*)Top_LinkStack(stack);
int right = tmp->val;
Pop_LinkStack(stack);
free(tmp);
//获取左操作数
tmp = (Mychar*)Top_LinkStack(stack);
int left = tmp->val;
Pop_LinkStack(stack);
free(tmp);
//运算
int ret = MyOperate(*p, left, right);
//结果放回栈中
Mychar *myc1 = (Mychar*)malloc(sizeof(Mychar));
myc1->val = ret;
Push_LinkStack(stack, (LinkSNode*)myc1);
}
p++;
}
//输出结果
if (Size_LinkStack(stack) == 1) {
Mychar *myc1 = (Mychar*)Top_LinkStack(stack);
printf("运算结果为:%d\n", myc1->val);
Pop_LinkStack(stack);
free(myc1);
}
//释放栈
Destory_LinkStack(stack);
}
int main() {
test01();
return 0;
}
总结后缀表达式:此例子总的来说也不算难,知道两个签个前提即可自行写出。