数据结构——栈

1 栈的定义

栈是一种数据结构,类似于枪的弹夹安装子弹,先安装的子弹最后弹出,后安装的子弹先弹出。
栈的具体定义:

typedef double ElemType;
typedef struct
{
	ElemType *base;//指向栈底的指针变量
	ElemType *top;//指向栈顶的指针变量
	int StackSize;//当前最大容量
}sqStack;

2 栈的基本操作

  • Init:栈的初始化
    -Push(): 向栈中插入数据
  • Pop():从栈中弹出数据
    可以参考下图理解:
    在这里插入图片描述

2.1 初始化操作

  • 为栈底指针分配内存
  • 将栈底指针赋值给栈顶指针,即战帝与栈顶指针指向同一位置,栈为空
  • 给栈一个初始大小
void InitStack(sqStack *s)
{
	s->base = (ElemType *)malloc(Stack_InitSize * sizeof(ElemType));
	if (!s->base)
		exit(0);
	s->top = s->base;
	s->StackSize = Stack_InitSize;
}

2.2 插入操作(入栈)

  • 将元素赋值给顶部指针,此时顶部和底部指针都指向元素的地址
  • 将顶部指针++,指向下一个空的地址。
void Push(sqStack *s,ElemType e)
{
	*(s->top)= e;
	s->top++;
}

2.3 弹出操作(出栈)

  • 判断栈是否为空
  • 让栈顶指针指向上一个元素
void Pop(sqStack *s,ElemType *e)
{
	if (s->base == s->top)
		return;
	*e=*(--(s->top));
}

3 实战

逆波兰计算器:
逆波兰表达式,它的语法规定,表达式必须以逆波兰表达式的方式给出。逆波兰表达式又叫做后缀表达式。下面是一些例子:
正常的表达式 逆波兰表达式

  • a+b —> a,b,+
  • a+(b-c) —> a,b,c,-,+
  • a+(b-c)d —> a,b,c,-,d,,+
  • a+d*(b-c)—>a,d,b,c,-,*,+
  • a=1+3 —> a,1,3,+,=
    下面是具体代码:
#include<stdio.h>
#include<math.h>
#include<ctype.h>
#include<stdlib.h>

//支持小数点
#define STACK_INIT_SIZE 20
#define STACKINCREMENT 10
#define MAXBUFFER 10

typedef double ElemType;
typedef struct
{
	ElemType *base;
	ElemType *top;
	int StackSize;
}sqStack;

void InitStack(sqStack *s)
{
	s->base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));
	if (!s->base)
		exit(0);

	s->top = s->base;
	s->StackSize = STACK_INIT_SIZE;
}

void push(sqStack *s, ElemType e)
{
	if (s->top - s->base >= s->StackSize)
	{
		s->base = (ElemType*)realloc(s->base, (s->StackSize + STACKINCREMENT) * sizeof(ElemType));
		if (!s->base) { exit(0); }
	}
	*(s->top) = e;
	s->top++;
}

void pop(sqStack *s, ElemType *e)
{
	if (s->top == s->base)
	{
		return;
	}
	*e = *--(s->top);
}

int StackLen(sqStack s)
{
	return (s.top - s.base);
}
int main()
{
	sqStack s;
	char c;
	double d, e;
	char str[MAXBUFFER];
	int i = 0;

	InitStack(&s);

	printf("请按照逆波兰表达式输入带计算数据,数据与运算符之间用空格隔开,以#作为结束标志:\n");
	scanf_s("%c", &c);
	while (c != '#')
	{
		while (isdigit(c) || c == '.')//用于过滤数据,若参数c为阿拉伯数字0~9,则返回非0值,否则返回0。
		{
			str[i++] = c;//缓冲区,可以将12连在一起
			str[i] = '\0';
			if (i >= 10)
			{
				printf("出错,输入单个数据过大!\n");
				return -1;
			}
			scanf_s("%c", &c);
			if (c == ' ')//有空格代表一个数据传入结束,比如12 3
			{
				d = atof(str);//将char型数字转化为double型,这个string是将 12 3将12合在一起了
				push(&s, d);
				i = 0;
				break;
			}
		}

		switch (c)
		{
		case '+':
			pop(&s, &e);
			pop(&s, &d);
			push(&s, d + e);
			break;

		case '-':
			pop(&s, &e);
			pop(&s, &d);
			push(&s, d - e);
			break;

		case '*':
			pop(&s, &e);
			pop(&s, &d);
			push(&s, d*e);
			break;

		case '/':
			pop(&s, &e);
			pop(&s, &d);
			if (e != 0) {
				push(&s, d / e);
			}
			else
			{
				printf("\n出错:除数为0!\n");
				return -1;
			}
			break;
		}
		scanf_s("%c", &c);
	}
	pop(&s, &d);
	printf("\n最终的计算结果是:%f\n", d);

	//system("pause");
	return 0;
}

实现结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值