栈的基本操作c语言
- 格式:doc
- 大小:21.00 KB
- 文档页数:6
c语言栈计算表达式在计算机科学中,栈是一种非常重要的数据结构,被广泛应用于编译器、操作系统、网络通信等领域。
在本文中,我们将探讨如何使用C语言实现栈来计算表达式。
表达式是由操作数、操作符和括号组成的数学式子,例如:3 + 4 * 2 / (1 - 5)。
在计算表达式时,我们需要遵循一定的计算规则,如乘除法优先于加减法,括号内的计算优先于括号外的计算等。
我们可以使用栈来实现对表达式的计算。
具体步骤如下:1. 定义两个栈:一个操作数栈和一个操作符栈。
2. 从左到右遍历表达式的每一个字符,如果是数字则将其压入操作数栈;如果是操作符则将其压入操作符栈,并根据运算规则进行计算。
3. 在遍历完成后,操作符栈中可能还有未计算的操作符,需要继续计算,直到操作符栈为空。
4. 最终操作数栈中只剩下一个数,即为表达式的计算结果。
下面是一段示例代码,用于计算简单的表达式:```#include <stdio.h>#include <stdlib.h>#include <ctype.h>#define MAX_SIZE 100typedef struct {int data[MAX_SIZE];int top;} Stack;void initStack(Stack *s) {s->top = -1;}void push(Stack *s, int item) { if (s->top == MAX_SIZE - 1) { printf('Stack Overflow');exit(1);}s->data[++s->top] = item;}int pop(Stack *s) {if (s->top == -1) {printf('Stack Underflow');exit(1);}return s->data[s->top--];}int isEmpty(Stack *s) {return s->top == -1;}int isFull(Stack *s) {return s->top == MAX_SIZE - 1;}int peek(Stack *s) {return s->data[s->top];}int evaluate(char *expr) {Stack operandStack, operatorStack; initStack(&operandStack);initStack(&operatorStack);int i = 0;while (expr[i] != '0') {if (isdigit(expr[i])) {int num = 0;while (isdigit(expr[i])) {num = num * 10 + (expr[i] - '0'); i++;}push(&operandStack, num);}else if (expr[i] == '(') {push(&operatorStack, expr[i]);i++;}else if (expr[i] == ')') {while (!isEmpty(&operatorStack) && peek(&operatorStack) != '(') {int op2 = pop(&operandStack);int op1 = pop(&operandStack);char op = pop(&operatorStack);int result;switch (op) {case '+':result = op1 + op2;break;case '-':result = op1 - op2;break;case '*':result = op1 * op2;break;case '/':result = op1 / op2;break;}push(&operandStack, result);}pop(&operatorStack);i++;}else if (expr[i] == '+' || expr[i] == '-' || expr[i] == '*' || expr[i] == '/') {while (!isEmpty(&operatorStack) &&peek(&operatorStack) != '(' &&((expr[i] == '*' || expr[i] == '/') || (expr[i] == '+' || expr[i] == '-') &&(peek(&operatorStack) == '*' || peek(&operatorStack) == '/'))) {int op2 = pop(&operandStack);int op1 = pop(&operandStack);char op = pop(&operatorStack);int result;switch (op) {case '+':result = op1 + op2;break;case '-':result = op1 - op2;break;case '*':result = op1 * op2;break;case '/':result = op1 / op2;break;}push(&operandStack, result); }push(&operatorStack, expr[i]); i++;}else {i++;}}while (!isEmpty(&operatorStack)) { int op2 = pop(&operandStack);int op1 = pop(&operandStack);char op = pop(&operatorStack);int result;switch (op) {case '+':result = op1 + op2;break;case '-':result = op1 - op2;break;case '*':result = op1 * op2;break;case '/':result = op1 / op2;break;}push(&operandStack, result);}return pop(&operandStack);}int main() {char expr[MAX_SIZE];printf('Enter an expression: ');fgets(expr, MAX_SIZE, stdin);int result = evaluate(expr);printf('Result = %d', result);return 0;}```在这段代码中,我们定义了一个栈结构体,包含了栈的数据和栈顶指针。
C语言中栈的基本操作栈(Stack)是一种遵循“后进先出”(LIFO)原则的数据结构,具有以下几个基本操作:入栈(Push)、出栈(Pop)、判断栈是否为空(Empty)以及获取栈顶元素(Top)。
下面将详细介绍这些基本操作。
1. 入栈(Push):将一个元素添加到栈的顶部。
入栈操作分为两个步骤:(1)判断栈是否已满,如果已满则无法再添加元素;(2)若栈不满,则将元素添加到栈的顶部,并更新栈顶指针。
具体实现代码如下:```void push(Stack *s, int item)if (is_full(s))printf("Stack is full, cannot push more elements.\n");return;}s->top++;s->data[s->top] = item;}```2. 出栈(Pop):将栈顶元素移除,并返回该元素的值。
出栈操作也有两个步骤:(1)判断栈是否为空,如果为空则无法进行出栈操作;(2)若栈不为空,则将栈顶元素移除,并更新栈顶指针。
具体实现代码如下:```int pop(Stack *s)int item;if (is_empty(s))printf("Stack is empty, cannot pop any elements.\n");return -1; // 指定一个特定的返回值来表示错误}item = s->data[s->top];s->top--;return item;}```3. 判断栈是否为空(Empty):判断栈是否为空分为两种情况,一种是根据栈顶指针进行判断,另一种是根据数据数量进行判断。
(1)判断栈顶指针是否为-1,若为-1则说明栈为空;(2)若栈内数据数量为0,则栈为空。
具体实现代码如下:```int is_empty(Stack *s)return s->top == -1; // 栈顶指针为-1表示栈为空}```4. 获取栈顶元素(Top):返回栈顶元素的值,但不对栈做任何修改。
用堆栈实现四则运算c语言堆栈是一种常见的数据结构,它符合先进后出的原则。
在四则运算中,我们可以借助堆栈这种数据结构实现运算,方便高效,不易出错。
堆栈的实现包括两个基本操作:Push(入栈)和Pop(出栈)。
我们可以以此设计四则运算。
首先,我们需要将输入的四则运算表达式转换成后缀表达式。
后缀表达式也叫逆波兰表达式,相对于中缀表达式而言,运算符在后面,操作数在前面,这样方便计算机进行读取和计算。
例如:中缀表达式:5+3*2后缀表达式:5 3 2 * +将中缀表达式转换成后缀表达式,我们需要用到堆栈。
具体的实现方法是,从左向右遍历表达式,如果是数字,则直接输出;如果是符号,则将其与堆栈顶的符号进行比较,如果优先级高就入栈,否则不断将符号出栈并输出,直到当前符号优先级大于堆栈顶符号优先级,最后将当前符号入栈。
例如:表达式:5+3*2堆栈操作:1.将5输出,堆栈为空2.遇到+号,入栈3.将3输出,堆栈顶为+号4.遇到*号,入栈5.将2输出,堆栈顶为*号6.输出*号,堆栈顶为+号7.输出+号,堆栈为空得到后缀表达式:5 3 2 * +有了后缀表达式,我们可以用堆栈进行计算。
具体方法是,从左向右遍历后缀表达式,如果是数字则入栈,如果是符号则将栈顶两个数字出栈并进行计算,将结果入栈,最终得到最终的计算结果。
例如:后缀表达式:5 3 2 * +堆栈操作:1.将5入栈2.将3入栈3.遇到*号,出栈3和2,进行计算得到6,将6入栈4.将栈顶元素5出栈5.遇到+号,出栈6和5,进行计算得到11,将11入栈得到计算结果:11通过堆栈实现四则运算,可以有效简化我们的计算流程,避免复杂的优先级判断和计算错误。
同时,堆栈为我们提供了一种更加高效的数据结构,不仅在四则运算中可以发挥作用,在其他应用中也很常见。
当然,在实际应用中,我们需要考虑到多种情况的处理,例如负数、小数、括号等,以及错误处理等细节问题,才能保证算法的正确性和可靠性。
c语⾔stack(栈)和heap(堆)的使⽤详解⼀、预备知识—程序的内存分配⼀个由C/C++编译的程序占⽤的内存分为以下⼏个部分1、栈区(stack)—由编译器⾃动分配释放,存放函数的参数值,局部变量的值等。
其操作⽅式类似于数据结构中的栈。
2、堆区(heap)—⼀般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。
注意它与数据结构中的堆是两回事,分配⽅式倒是类似于链表。
3、全局区(静态区)(static)—全局变量和静态变量的存储是放在⼀块的,初始化的全局变量和静态变量在⼀块区域,未初始化的全局变量和未初始化的静态变量在相邻的另⼀块区域。
程序结束后由系统释放。
4、⽂字常量区—常量字符串就是放在这⾥的。
程序结束后由系统释放。
5、程序代码区—存放函数体的⼆进制代码。
⼆、例⼦程序复制代码代码如下://main.cppint a=0; //全局初始化区char *p1; //全局未初始化区main(){intb;栈char s[]="abc"; //栈char *p2; //栈char *p3="123456"; //123456\0在常量区,p3在栈上。
static int c=0; //全局(静态)初始化区p1 = (char*)malloc(10);p2 = (char*)malloc(20); //分配得来得10和20字节的区域就在堆区。
strcpy(p1,"123456"); //123456\0放在常量区,编译器可能会将它与p3所向"123456"优化成⼀个地⽅。
}三、堆和栈的理论知识2.1申请⽅式stack:由系统⾃动分配。
例如,声明在函数中⼀个局部变量int b;系统⾃动在栈中为b开辟空间heap:需要程序员⾃⼰申请,并指明⼤⼩,在c中⽤malloc函数如p1=(char*)malloc(10);在C++中⽤new运算符如p2=(char*)malloc(10);但是注意p1、p2本⾝是在栈中的。
顺序栈的基本操作顺序栈是一种通用的数据结构,它主要用于存储和操作栈中的数据。
它利用存储结构来实现快速入栈、出栈操作,不仅可以更好地利用空间,而且可以减少操作耗时。
因此,顺序栈是算法与数据结构的重要组成部分,在许多应用程序中有着广泛的应用,比如括号匹配、表达式求值等等。
本文旨在针对顺序栈的基本操作进行介绍,以便更好地理解和使用顺序栈。
顺序栈的基本操作是入栈和出栈。
入栈操作也叫压栈操作,即将元素添加到栈的顶部,这是数据结构中最简单的操作,只需要将新元素添加到栈顶,即可完成入栈操作,操作完后,栈的大小将增加1。
出栈操作也称为弹栈操作,它将栈顶元素弹出,即将栈顶元素移除,这一操作也是简单的,只需将栈顶元素弹出,即可完成出栈操作,操作完后,栈的大小将减少1。
除了入栈和出栈,顺序栈还有几种操作,比如查看栈顶元素、获取栈元素的数量和判断栈是否为空等。
查看栈顶元素操作是指,在不改变栈的状态的前提下,查看栈顶元素的值,也就是返回栈顶元素的值,但不会弹出栈顶元素。
而获取栈中元素的数量操作是指,获取栈中当前元素的个数,而判断栈是否为空操作,则是指判断栈中是否有元素,如果没有元素,则认为栈是空的。
另外,顺序栈还有一种特殊的操作,叫做清空栈操作。
这个操作将栈中所有的元素都清空,即把栈中所有的元素都弹出,从而让栈变为空栈的状态。
此外,有时候顺序栈可能会溢出,这时候就需要扩展栈的容量,以便容纳更多的元素。
这个过程叫做栈的扩容操作,操作时根据当前栈容量来增加栈容量,一般来说,扩容操作涉及到栈的动态分配内存和释放内存,这需要一定的耗时和内存开销,因此在实际应用中,我们需要设计一个合理的栈容量,以避免不必要的内存开销。
综上所述,顺序栈是一种简单又实用的数据结构,它的基本操作是入栈、出栈、查看栈顶元素、获取栈元素的数量、判断栈是否为空和清空栈等操作。
此外,它还有扩容操作,可以扩充栈的容量,以容纳更多的元素,因此,在实际开发中,我们需要仔细考虑栈的容量设计,以避免不必要的内存开销。
c语言入栈出栈代码C语言是一种广泛使用的编程语言,它具有高效、简洁、灵活等特点,因此在计算机科学领域中得到了广泛的应用。
在C语言中,入栈出栈是一种非常重要的操作,它可以帮助我们实现很多有用的功能。
本文将介绍C语言中的入栈出栈操作,并提供一些示例代码,帮助读者更好地理解这些操作。
一、什么是栈在介绍入栈出栈操作之前,我们需要先了解一下什么是栈。
栈是一种数据结构,它具有后进先出(LIFO)的特点。
也就是说,最后进入栈的元素最先被取出。
栈可以用数组或链表来实现,但是数组实现的栈比较简单,因此我们在本文中只介绍数组实现的栈。
二、栈的基本操作栈的基本操作包括入栈和出栈。
入栈操作将一个元素压入栈中,出栈操作将栈顶元素弹出。
下面是栈的基本操作的代码实现:```c#define MAXSIZE 100 // 栈的最大容量typedef struct {int data[MAXSIZE]; // 栈的数据int top; // 栈顶指针} Stack;// 初始化栈void initStack(Stack *s) {s->top = -1;}// 判断栈是否为空int isEmpty(Stack *s) {return s->top == -1;}// 判断栈是否已满int isFull(Stack *s) {return s->top == MAXSIZE - 1; }// 入栈操作void push(Stack *s, int x) {if (isFull(s)) {printf("Stack is full.\n");return;}s->top++;s->data[s->top] = x;}// 出栈操作int pop(Stack *s) {if (isEmpty(s)) {printf("Stack is empty.\n");return -1;}int x = s->data[s->top];s->top--;return x;}```在上面的代码中,我们定义了一个结构体Stack,它包含一个数组data和一个指针top。
#include <stdlib.h>
#include <stdio.h>
#include <iomanip.h>
//函数结果状态代码
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
//Status 是函数的类型,其值是函数结果状态代码
typedef int Status;
typedef int SetElemType;
typedef SetElemType ElemType;
#include "tou.h"
#include <stdio.h>
#include <malloc.h>
typedef char SElemType; // 栈的元素类型
#define STACK_INIT_SIZE 100 // 存储空间初始分配量
#define STACKINCREMENT 10 // 存储空间分配增量
// 栈的顺序存储表示P46
typedef struct SqStack
{
SElemType *base; // 在栈构造之前和销毁之后,base的值为NULL SElemType *top; // 栈顶指针
int stacksize; // 当前已分配的存储空间,以元素为单位
}SqStack; // 顺序栈
// 构造一个空栈S。
int InitStack(SqStack *S)
{
// 为栈底分配一个指定大小的存储空间
(*S).base = (SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if( !(*S).base )
exit(OVERFLOW); // 存储分配失败
(*S).top = (*S).base; // 栈底与栈顶相同表示一个空栈
(*S).stacksize = STACK_INIT_SIZE;
return 1;
}
// 若栈S为空栈(栈顶与栈底相同的),则返回1,否则返回0。
int StackEmpty(SqStack S)
{
if(S.top == S.base)
return 1;
else
return 0;
}
// 插入元素e为新的栈顶元素。
int Push(SqStack *S, SElemType e)
{
if((*S).top - (*S).base >= (*S).stacksize) // 栈满,追加存储空间
{
(*S).base = (SElemType *)realloc((*S).base,
((*S).stacksize + STACKINCREMENT) * sizeof(SElemType));
if( !(*S).base )
exit(0); // 存储分配失败
(*S).top = (*S).base+(*S).stacksize;
(*S).stacksize += STACKINCREMENT;
}
*((*S).top)++=e;
// 这个等式的++ * 优先级相同,但是它们的运算方式,是自右向左
return 1;
}
// 若栈不空,则删除S的栈顶元素,用e返回其值,并返回1;否则返回0。
int Pop(SqStack *S,SElemType *e)
{
if((*S).top == (*S).base)
return 0;
*e = *--(*S).top;
// 这个等式的++ * 优先级相同,但是它们的运算方式,是自右向左
return 1;
}
// 销毁栈S,S不再存在。
int DestroyStack(SqStack *S)
{
free((*S).base); //释放栈底的空间,并置空
(*S).base = NULL;
(*S).top = NULL;
(*S).stacksize = 0;
return 1;
}
// 把S置为空栈。
int ClearStack(SqStack *S)
{
(*S).top = (*S).base; //栈底栈顶相同为空栈
return 1;
}
// 返回S的元素个数,即栈的长度。
int StackLength(SqStack S)
{
// 栈顶指针减去栈底指针刚好等于长度,因为栈顶指针指向当前栈// 顶元素的下一个位置。
return S.top - S.base;
}
// 若栈不空,则用e返回S的栈顶元素,并返回1;否则返回0。
int GetTop(SqStack S,SElemType *e)
{
if(S.top > S.base)
{
*e = *(S.top-1); // 栈顶指针的下一个位置为栈顶元素
return 1;
}
else
return 0;
}
// 从栈底到栈顶依次对栈中每个元素调用函数visit()。
int StackTraverse(SqStack S,int(*visit)(SElemType))
{
while(S.top>S.base)
visit(*S.base++);
printf("\n");
return 1;
}
int visit(SElemType c)
{
printf("%d ",c);
return 1;
}
#include "toutou.h"
int main()
{
int j,n,num;
SqStack s;
SElemType e;
// 创建一个顺序栈。
if(InitStack(&s) == 1)
printf("顺序栈创建成功!\n");
// 查看栈的长度。
printf("栈的长度是%d\n", StackLength(s));
// 查看栈是否为空。
printf("栈空否:%d(1:空0:否)\n",StackEmpty(s));
// 初始化栈。
printf("输入数据个数:");
scanf("%d",&n);
printf("输入数据:");
for(j = 1; j <= n; j++){scanf("%d",&num);
Push(&s, num);}
printf("栈中元素依次为:");
StackTraverse(s,visit);
Pop(&s,&e);
printf("弹出的栈顶元素e=%d\n",e);
GetTop(s,&e);
printf("栈顶元素e=%d 栈的长度为%d\n",e,StackLength(s));
ClearStack(&s);
printf("清空栈后,栈空否:%d(1:空0:否)\n",StackEmpty(s));
DestroyStack(&s);
printf("销毁栈成功");
return 0;
}
生于忧患,死于安乐《孟子•告子》
舜发于畎亩之中,傅说举于版筑之间,胶鬲举于鱼盐之中,管夷吾举于士,孙叔敖举于海,百里奚举于市。
故天将降大任于是人也,必先苦其心志,劳其筋骨,饿其体肤,空乏其身,行拂乱其所为,所以动心忍性,曾益其所不能。
人恒过,然后能改;困于心,衡于虑,而后作;征于色,发于声,而后喻。
入则无法家拂士,出则无敌国外患者,国恒亡。
然后知生于忧患,而死于安乐也。