赞
踩
栈是一种只能在一端进行插入或者删除操作的线性表。表中允许插入,删除操作的一端叫做栈顶,另一端叫栈底。
但栈没有数据元素时称为空栈,插入数据操作为进栈或入栈,删除数据操作为出栈或退栈。
栈的特点为后进先出,栈也成为后进先出表。如存入一组数据,顺序为1, 2, 3, 4,则出栈时顺序为4, 3, 2, 1 。
顺序栈采用顺序存储结构进行存储,分配一块连续的存储空间来存放栈中元素,并用一个变量(如int类型的top)指向当前的栈顶元素。
代码实现:
typedef struct{
int data[MaxSize];
int top;
}SqStack;
void InitStack(SqStack*& s) {
s = (SqStack*)malloc(sizeof(SqStack)); //分配空间,首地址放在s中
s->top = -1; //栈顶指针为-1;
}
void DestroyStack(SqStack* &s) {
free(s);
}
bool Push(SqStack*& s, int e) {
if (s->top == MaxSize - 1) return false; //判断是否栈满
s->top++;
s->data[s->top] = e;
return true;
}
bool Pop(SqStack*& s, int e) {
if (s->top == -1) return false; //栈为空
e = s->data[s->top]; //取出栈顶元素
s->top--;
return true;
}
链栈一般采用带头结点的单链来实现,相比顺序栈,链栈的优点就是不存在栈满溢出的问题。
在进行插入和删除操作时,采用头插法进行插入,删除即删除首结点,在更换头结点的下一个结点。
代码如下:
typedef struct node {
int e;
node* next;
};
void InitStack(node* &s) {
s = (node*)malloc(sizeof(node)); //栈顶指针为-1;
s->next = NULL; //栈空
}
void DestroyStack(node* &s) {
node* pre = s, * p = s->next; //pre为头结点, p为首结点
while (p != NULL) {
free(p);
pre = p; //更换头结点的位置,仍用pre指向头结点
p = pre->next; //p指向后一个结点,仍用p指向首结点
}
free(pre);
}
void Push(node*& s, int e) {
node* p = (node*)malloc(sizeof(node));
p->e = e; //存入数据
p->next = s->next; //让p连接后面的数据结点
s->next = p; //p成为新的首结点
}
bool Pop(node*& s, int e) {
node* p = s->next; //p为首结点
if (p == NULL) return false; //栈空
e = p->e; //取值
s->next = p->next; //删除首结点
free(p); //释放被删除结点的储存空间
return true;
}
输入包含±*/四种运算,(含有()括号的合法算术表达式,且操作数为多位整数,并计算其值,表达式以#开始,并以#结束)。
创建两个栈,一个运算符栈来存储运算符,一个数字栈来存储数字。
对一个输入的式子进行遍历,例如给一个字符数组str[100]赋值为 #(4+3)*12#
对str遍历
(1)第一为#存入运算符栈;
(2)遍历第二为‘(’,根据符号优先级,‘(’比‘#’优先级高,应该压入运算符栈;
(3)再第三次遍历为数字4,压入数字栈,并再压入一个‘|’来隔开下一位数字;
(4)第四次为‘+’,根据符号优先级,应该入运算符栈;
(5)第五压入数字3进数字栈,压入分隔符’|’;
(6)第六为‘)’,根据优先级比‘+’低,不应该入栈【判断是否运算符栈顶为‘(’,若是,把‘(’弹出,并遍历下一位str数组元素】,并且需要在数字栈中弹出两个数字进行运算【取出数字时,是一个顺序颠倒的字符数组,需要进行转化,如若取出为“|21”需转化为数字12】,在将运算结果压入数据栈,在压入一个分隔符’|‘;
(7)第七为元素为‘ * ’,比栈顶’#‘优先级高,入栈;
(8)第八为数字12,入栈,此时栈内数据为 |21|7
(9)最后是#,优先级最低,在数字栈弹出两个数字,运算符栈弹出*,进行计算,压入计算结果和分隔符;
将数字栈中的结果弹出,得到的是字符数组 |48,转化为int类型84;【转化方法如下代码】
了解运算符的优先级,参考下面代码的Panduan()函数;
可将数字栈的数据元素类型改为int类型,这样就无需进行字符数组反转再转化。也正由于栈的后进先出的特点,才需要对此问题进行处理。
参考代码
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<string.h> const int MaxSize = 100; typedef struct linknode { char data[MaxSize]; int top; }; void InitStack(linknode* &s) { s = (linknode*)malloc(sizeof(linknode)); s->top = -1; } bool Push(linknode* &s, char e) { if (s->top == MaxSize-1) { return false; } s->top++; s->data[s->top] = e; return true; } bool Pop(linknode*& s, char &a) { if (s->top == -1) { return false; } a = s->data[s->top]; s->top--; return true; } char GetTop(linknode* s) { return s->data[s->top]; } int PanDuan(char a, char b) { //-1表示a小于b 1表示a大于b 0表示相等 if (a == '+') { if (b == '#' || b == '+' || b == '-' || b == '(') return 1; else if (b == '/' || b == '*' || b == ')') return -1; } if (a == '-') { if (b == '#' || b == '-' || b == '+' || b == '(') return 1; else if (b == '/' || b == '*' || b == ')') return -1; } if (a == '*') { if (b == '+' || b == '-' || b == '*' || b == '/' || b == '(' || b == '#') return 1; else if (b == ')') return -1; } if (a == '/') { if (b == '+' || b == '-' || b == '*' || b == '/' || b == '(' || b == '#') return 1; else if (b == ')') return -1; } if (a == '(') { /*if (b == '-' || b == '+' || b == '*' || b == '/' || b == ')') return 1; else if (b == '(' || b == '#') return 1;*/ return 1; } if (a == ')') { if (b == '-' || b == '+' || b == '*' || b == '/' || b == '(') return -1; else if (b == ')'|| b == '#') return 0; } if (a == '#') { if (b == '-' || b == '+' || b == '*' || b == '/' || b == '(' || b == ')') return -1; else if (b == '#') return 0; } } void rev(char str[], int i) { int s = 0, e = i; char temp; while (s < e) { temp = str[s]; str[s] = str[e]; str[e] = temp; s++; e--; } } int ExpEvaluation(char str[]) { int result; //结果 char Rch[10] = ""; //结果字符数组 linknode* dataStack; //数字栈 linknode* optrStack; //运算符栈 InitStack(dataStack); InitStack(optrStack); int index = 0; //字符串索引 Push(optrStack, str[index]); index++; while (str[index] != '\0' || GetTop(optrStack) != '#') { if ('0' <= str[index] && str[index] <= '9') { //数字直接进入数字栈 Push(dataStack, str[index]); index++; if ('0' <= str[index] && str[index] <= '9') continue; else Push(dataStack, '|'); //用|隔开每一个数字 } else { if (PanDuan(str[index], GetTop(optrStack)) >= 0) { // a比栈顶的运算符优先级大 Push(optrStack, str[index]); index++; } else { char ch; if (optrStack->data[optrStack->top] == '(') { Pop(optrStack, ch); index++; continue; } char a[10] = {}, b[10] = {}, op; Pop(optrStack, op); int a1, b1; int flag = 0; int i = 0; Pop(dataStack, ch); while (1) { if (GetTop(dataStack) == '|' || dataStack->top == -1) break; Pop(dataStack, a[i]); i++; } rev(a, i - 1); char str[10]; //将a,b转化为字符串 sscanf(a, "%s", str, _countof(str)); sscanf(str, "%d", &a1); //将a间接转化为数字 Pop(dataStack, ch); i = 0; while (1) { if (GetTop(dataStack) == '|' || dataStack->top == -1) break; Pop(dataStack, b[i]); i++; } rev(b, i - 1); sscanf(b, "%s", str, _countof(str)); sscanf(str, "%d", &b1); //将b间接转化为数字 i = 0; switch (op) { case '-': result = b1 - a1; snprintf(Rch, sizeof(Rch), "%d", result); for (int i = 0; i < strlen(Rch); i++) { Push(dataStack, Rch[i]); } Push(dataStack, '|'); break; case '+': result = b1 + a1; snprintf(Rch, sizeof(Rch), "%d", result); for (int i = 0; i < strlen(Rch); i++) { Push(dataStack, Rch[i]); } Push(dataStack, '|'); break; case '*': result = a1 * b1; snprintf(Rch, sizeof(Rch), "%d", result); for (int i = 0; i < strlen(Rch); i++) { Push(dataStack, Rch[i]); } Push(dataStack, '|'); break; case '/': result = b1 / a1; snprintf(Rch, sizeof(Rch), "%d", result); for (int i = 0; i < strlen(Rch); i++) { Push(dataStack, Rch[i]); } Push(dataStack, '|'); break; } } } } char dataStackTop; //数字栈栈顶的‘|’ Pop(dataStack, dataStackTop); //去掉‘|’ int i = 0; while (dataStack->top != -1) { Pop(dataStack, Rch[i]); i++; } rev(Rch,i-1); sscanf(Rch, "%d", &result); return result; } int main() { printf("输入包含+-*/四种运算,(表达式以#开始,并以#结束):\n"); char str[MaxSize]; int result = 0; scanf_s("%s", str); result = ExpEvaluation(str); printf("\n结果为:%d", result); }
测试结果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。