栈的实现可以用指针和数组来实现,也可以用脚标作指针的功能。这里我们先用脚标来实现。
定义结构体:
typedef struct CharStack{
int top;//栈顶的脚标
int data[STACK_MAX_SIZE];//用于存储数据的空间
}*CharStackPtr;
栈的初始化
CharStackPtr charStackInit(){
CharStackPtr tempStack = (CharStackPtr)malloc(sizeof(struct CharStack));
tempStack->top = -1;//表示栈为空
return tempStack;
}
链表的打印:
这儿在写的时候犯了个小错误(用 top--;来输出—),应该用i来记录top,否则栈在输出的时候就被我们清空了
void outputStack(CharStackPtr paraStack) {
for (int i = paraStack->top; i >= 0; i --) {
printf("%c ", paraStack->data[i]);
}
printf("\r\n");
}
栈的输入输出
void push(CharStackPtr paraStack,int paraChar ){
if(paraStack->top >= STACK_MAX_SIZE-1){
printf("没有位置,不能再插入\r\n");
return;
}//判断栈是否满
paraStack->top ++;
printf("%d ",paraStack->top);
paraStack->data[paraStack->top] = paraChar;
}
char pop(CharStackPtr paraStack){
if(paraStack->top >= 0){
paraStack->top--;//指向下一个值
return paraStack->data[paraStack->top+1];//原本处理值
}else{
printf("栈为空\r\n");
return '\0';
}
}
完整代码
#include <stdio.h>
#include <malloc.h>
#define STACK_MAX_SIZE 10
typedef struct CharStack{
int top;
int data[STACK_MAX_SIZE];
}*CharStackPtr;
void outputStack(CharStackPtr paraStack) {
for (int i = paraStack->top; i >= 0; i --) {
printf("%c ", paraStack->data[i]);
}// Of for i
printf("\r\n");
}
CharStackPtr charStackInit(){
CharStackPtr tempStack = (CharStackPtr)malloc(sizeof( CharStack));
tempStack->top = -1;
return tempStack;
}
void push(CharStackPtr paraStack,int paraChar ){
if(paraStack->top >= STACK_MAX_SIZE-1){
printf("没有位置,不能再插入\r\n");
return;
}
paraStack->top ++;
printf("%d ",paraStack->top);
paraStack->data[paraStack->top] = paraChar;
}
char pop(CharStackPtr paraStack){
if(paraStack->top >= 0){
paraStack->top--;
return paraStack->data[paraStack->top+1];
}else{
printf("栈为空\r\n");
return '\0';
}
}
void pushPopTest() {
printf("---- pushPopTest begins. ----\r\n");
CharStackPtr tempStack = charStackInit();
printf("After initialization, the stack is: ");
outputStack(tempStack);
char ch;
for (ch = 'a'; ch < 'm'; ch ++) {
printf("Pushing %c.\r\n", ch);
push(tempStack, ch);
outputStack(tempStack);
}
for (int i = 0; i < 3; i ++) {
ch = pop(tempStack);
if(ch){
printf("Pop %c.\r\n", ch);
}
outputStack(tempStack);
}
printf("---- pushPopTest ends. ----\r\n");
}
int main() {
pushPopTest();
}
栈的应用——括号匹配及计算多项式
如 {[()]}为正确,{[}]错误,这儿的括号匹配融入进计算多项式中,由于这里二者融合了就只做了()的判断,在学习多项式计算要多自己手动画图,跟着逻辑走,才能更好的理解与掌握。
这里我采用了两个栈,一个栈存储数据,一个用于存储运算符,边读边计算,读到两个连续的运算符号的第二个时(由于这里涉及到两个运算符,有一个必定是存储于栈中),先不必慌着进栈,先判断两者优先级,若前者优先级高或者两者优先级相等,则优先级高的运算符弹出栈,存储数据的栈弹出两个数据用于计算,再将优先级低的存进栈中;若后者更高则直接存储。当整个计算式读完之后,存储运算符的不为空则继续进行计算,直到存储运算符的栈中运算符全部弹出(计算时读完以后,尽管边读边计算,依旧会存在没有计算的情况)。具体理解请画图跟踪;
完整代码
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#define Max 1000
typedef struct CharStack{
int top;
int data[Max];
}*CharStackPtr;//定义结构体
CharStackPtr CharStackInit(){
CharStackPtr tempStack = (CharStackPtr)malloc(sizeof(struct CharStack));
tempStack->top = 0;
tempStack->data[tempStack->top] = '#';
return tempStack;
}//栈的初始化
void output(CharStackPtr paraStack){
printf("计算结果是%d",paraStack->data[paraStack->top]);
}
void push(CharStackPtr paraStackPtr,int paraValue){
if(paraStackPtr->top >= Max-1){
printf("栈已满,不能再输入\r\n");
return;
}//判断栈是否满了
paraStackPtr->top++;
paraStackPtr->data[paraStackPtr->top] = paraValue;
}// 栈的初始化
char popChar(CharStackPtr paraStackPtr){
if(paraStackPtr->data[paraStackPtr->top]=='#'){
return '\0';
}else{
paraStackPtr->top--;
return paraStackPtr->data[paraStackPtr->top+1];
}
}//用于弹出栈的运算符
int popNum(CharStackPtr paraStackPtr){
if(paraStackPtr->data[paraStackPtr->top]=='#'){
return '\0';
}else{
paraStackPtr->top--;
return paraStackPtr->data[paraStackPtr->top+1];
}
}//弹出栈中的运算数字
int eval(CharStackPtr paraStackPtr,CharStackPtr paraNumPtr){
int a = popNum(paraNumPtr);
int b = popNum(paraNumPtr);
char c = popChar(paraStackPtr);
int x;
if(c == '+') x = a+b;
else if(c == '-') x = b-a;
else if(c == '*') x = a*b;
else x = b/a;
push(paraNumPtr,x);
}//对数字进行计算
bool checkput(CharStackPtr paraStackPtr){
if(popChar(paraStackPtr)=='('){
return true;
}else{
return false;
}
}//判断括号输入是否正确
int JudgeFirst(char s){
if(s=='+'||s=='-') return 1;
else return 2;
}//设计运算优先级
int main(){
while(1) {
char str[Max];
scanf("%s",&str);
int i=0,j;
CharStackPtr num = CharStackInit();//该栈用于存储数据
CharStackPtr ch1= CharStackInit(); //该栈用于存储运算符
CharStackPtr ch2= CharStackInit(); //用于存储括号,方便判断括号输入是否匹配
j=strlen(str);
for(i=0;i<j;i++){
char c = str[i];
if('0'<=c && c<= '9'){
int x = 0,j = i;
while(j<strlen(str) && ('0'<=str[j]&& str[j]<='9')){
x = x*10+str[j]-'0';
j++;
}
i = j-1;
push(num,x);
}//读取数据
else if(c =='('){
push (ch1,c);
push (ch2,c);
}
else if(c==')'){
if(checkput(ch2) == 0){
printf("输入错误,请检查括号是否匹配\r\n");
popChar(ch2);
}else{
while(ch1->data[ch1->top]!='(')eval(ch1,num);
popChar(ch1);
}
}else{
while(ch1->top!=0&&ch1->data[ch1->top] != '('&& (JudgeFirst(ch1->data[ch1->top])>=JudgeFirst(str[i]))){
eval(ch1,num);
}
push(ch1,c);
}//存储运算符,并在一定条件下进行计算
}
while(ch1->data[ch1->top]!='#') eval(ch1,num);
//判断括号输入的正确性
if(ch2->data[ch2->top]!='#'){
printf("输入错误,请检查括号是否匹配\r\n");
return 0;
}else{
output(num);
}
}
}
测试结果