10黑马笔记之栈的应用_根据后缀表达式求解

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;
}

总结后缀表达式:此例子总的来说也不算难,知道两个签个前提即可自行写出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值