1,栈的定义
栈是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。
2.栈的基本操作
操作代码
1.定义
typedef struct Stack
{
int top;
int data[MAX_SIZE];
} *StackPtr;
2.初始化
StackPtr initStack()
{
StackPtr resultPtr = (StackPtr)malloc(sizeof(struct Stack));
resultPtr->top = -1;
return resultPtr;
}
3.打印
void outputStack(StackPtr paraStack)
{
for(int i=0;i<=paraStack->top;i++)
{
printf("%c ",paraStack->data[i]);
}
printf("\r\n");
}
4.入栈
//入栈
void push(StackPtr paraStackPtr,int paraValue)
{
//判断是否栈满
if(paraStackPtr->top >= MAX_SIZE)
{
printf("栈满,不能添加\r\n");
return;
}
paraStackPtr->top ++;
paraStackPtr->data[paraStackPtr->top] = paraValue;
}
5.出栈
char pop(StackPtr paraStackPtr)
{
//判断空栈
if(paraStackPtr->top < 0)
{
printf("空栈,不能删除\r\n");
return '\0';
}
paraStackPtr->top --;
return paraStackPtr->data[paraStackPtr->top + 1];
}
6.提取栈顶
//提取栈顶
int getTop(StackPtr paraStackPtr)
{
//判断空栈
if(paraStackPtr->top < 0)
{
printf("空栈,不能提取\r\n");
return '\0';
}
return paraStackPtr->data[paraStackPtr->top];
}
功能测试
void pushPopText()
{
printf("栈进出测试开始:\r\n");
//初始化
StackPtr tempStack = initStack();
printf("初始化后的栈:");
outputStack(tempStack);
//入栈
for(char ch='a';ch<'n';ch++)
{
printf("添加%c:",ch);
push(tempStack,ch);
outputStack(tempStack);
}
//出栈
for(int i=0;i<4;i++)
{
char ch=pop(tempStack);
printf("删除%c:",ch);
outputStack(tempStack);
}
printf("测试结束。\r\n");
printf("\r\n");
}
测试结果
栈进出测试开始:
初始化后的栈:
添加a:a
添加b:a b
添加c:a b c
添加d:a b c d
添加e:a b c d e
添加f:a b c d e f
添加g:a b c d e f g
添加h:a b c d e f g h
添加i:a b c d e f g h i
添加j:a b c d e f g h i j
添加k:a b c d e f g h i j k
添加l:栈满,不能添加
a b c d e f g h i j k
添加m:栈满,不能添加
a b c d e f g h i j k
删除k:a b c d e f g h i j
删除j:a b c d e f g h i
删除i:a b c d e f g h
删除h:a b c d e f g
测试结束。
3.括号匹配应用
操作代码
bool bracketMatch(char* paraString,int paraLength)//只有true和false两个返回值
{
//初始化,将#放入栈底
StackPtr tempStack = initStack();
push(tempStack,'#');
char tempChar,tempPopedChar;
for(int i=0;i<paraLength;i++)
{
tempChar = paraString[i];
switch(tempChar)
{
case'(':
case'[':
case'{':
push(tempStack,tempChar);
break;
case')':
tempPopedChar = pop(tempStack);
if(tempPopedChar != '(')
{
return false;
}
break;
case']':
tempPopedChar = pop(tempStack);
if(tempPopedChar != '[')
{
return false;
}
break;
case'}':
tempPopedChar = pop(tempStack);
if(tempPopedChar != '{')
{
return true;
}
break;
default:
break;
}
}
tempPopedChar = pop(tempStack);
if(tempPopedChar != '#')
{
return false;
}
return true;
}
功能测试
void bracketMatchText()
{
printf("括号匹配测试开始:\r\n");
char* tempExpression = "{7+2-[4+6*(7-3)]}/3";
bool tempMatch = bracketMatch(tempExpression,17);
printf("‘%s’是否括号匹配? %d\r\n",tempExpression,tempMatch);
tempExpression = "[7-8*6)(]";
tempMatch = bracketMatch(tempExpression,9);
printf("‘%s’是否括号匹配? %d\r\n",tempExpression,tempMatch);
tempExpression = "(()[])";
tempMatch = bracketMatch(tempExpression,6);
printf("‘%s’是否括号匹配? %d\r\n",tempExpression,tempMatch);
tempExpression = "{]()";
tempMatch = bracketMatch(tempExpression,4);
printf("‘%s’是否括号匹配? %d\r\n",tempExpression,tempMatch);
printf("测试结束。\r\n");
printf("\r\n");
}
测试结果
括号匹配测试开始:
‘{7+2-[4+6*(7-3)]}/3’是否括号匹配? 1
‘[7-8*6)(]’是否括号匹配? 0
‘(()[])’是否括号匹配? 1
‘{]()’是否括号匹配? 0
测试结束。
4.多项式计算应用
C语言操作代码
//优先级关系(运用二维数组表示优先级关系,虽然代码繁琐,但是直观明了,不易出错)
char priority(char ch1,char ch2)
{
int i,j;
char pri[7][7]={// + - * / ( ) =
{'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},
{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},
{'<','<','<','<','<','=','0'},
{'>','>','>','>','0','>','>'},
{'<','<','<','<','<','0','='}
};
switch(ch1)
{
case '+': i = 0;
break;
case '-': i = 1;
break;
case '*': i = 2;
break;
case '/': i = 3;
break;
case '(': i = 4;
break;
case ')': i = 5;
break;
case '=': i = 6;
break;
}
switch(ch2)
{
case '+': j = 0;
break;
case '-': j = 1;
break;
case '*': j = 2;
break;
case '/': j = 3;
break;
case '(': j = 4;
break;
case ')': j = 5;
break;
case '=': j = 6;
break;
}
return pri[i][j];
}
//计算
int evaluate(int a,char ch,int b)
{
int result;
switch(ch)
{
case'+':
return a+b;
case'-':
return a-b;
case'*':
return a*b;
case'/':
if(b != 0)
return a/b;
else
{
printf("除数为0,无法计算\n");
}
}
}
//判断运算符和操作符
int judge(char ch)//运算符返回1,操作符返回0
{
switch(ch)
{
case'+':
case'-':
case'*':
case'/':
case'(':
case')':
case'=':
return 1;
default:
return 0;
}
}
//多项式计算
int evaluateExpression(char *paraExpression)
{
StackPtr tempStack1=initStack();//运算数栈
StackPtr tempStack2=initStack();//运算符栈
int a,b,ch,x,x1,x2;//x存放多余出栈元素,x1,x2用于计算
char cha;
int i = 0;
push(tempStack2,'=');//多项式以'='结尾
cha = paraExpression[i++];
while(cha != '=' || getTop(tempStack2) != '=')
{
if(judge(cha))//判断是否为运算符
{
switch(priority(getTop(tempStack2),cha))
{
case'<':
push(tempStack2,cha);
cha = paraExpression[i++];
break;
case'>':
ch = pop(tempStack2);
b = pop(tempStack1);
a = pop(tempStack1);
push(tempStack1,evaluate(a,ch,b));
break;
case'=':
x = pop(tempStack2);
cha = paraExpression[i++];
break;
}
}
else if(isdigit(cha))
{
x1 = cha-'0';
push(tempStack1,x1);
x2 = x1;
cha = paraExpression[i++];
while(isdigit(cha))判断是否为运算数,是则返回1(存储于ctype.h头文件中)
{
x1 = cha - '0';
x2 = 10*x2 + x1;
x = pop(tempStack1);
push(tempStack1,x2);
cha = paraExpression[i++];
}
}
else if(cha == ' ')
{
while(cha == ' ')
{
cha == paraExpression[i++];
}
}
else
{
printf("多项式错误\n");
}
}
return getTop(tempStack1);
}
功能测试
void evaluateExpressionText()
{
printf("多项式计算测试开始:\n");
int result;
char *tempExpression="7-6*8/2=";
result = evaluateExpression(tempExpression);
printf("%s%d\n",tempExpression,result);
tempExpression="3+6*9=";
result = evaluateExpression(tempExpression);
printf("%s%d\n",tempExpression,result);
tempExpression="7*(4+2)-(3*5)=";
result = evaluateExpression(tempExpression);
printf("%s%d\n",tempExpression,result);
printf("测试结束。\n");
}
测试结果
多项式计算测试开始:
7-6*8/2=-17
3+6*9=57
7*(4+2)-(3*5)=27
测试结束。
总代码
#include <stdio.h>
#include <malloc.h>
#include <ctype.h>
#define MAX_SIZE 10
//定义
typedef struct Stack
{
int top;
int data[MAX_SIZE];
} *StackPtr;
//初始化
StackPtr initStack()
{
StackPtr resultPtr = (StackPtr)malloc(sizeof(struct Stack));
resultPtr->top = -1;
return resultPtr;
}
//打印
void outputStack(StackPtr paraStack)
{
for(int i=0;i<=paraStack->top;i++)
{
printf("%c ",paraStack->data[i]);
}
printf("\r\n");
}
//入栈
void push(StackPtr paraStackPtr,int paraValue)
{
//判断是否栈满
if(paraStackPtr->top >= MAX_SIZE)
{
printf("栈满,不能添加\r\n");
return;
}
paraStackPtr->top ++;
paraStackPtr->data[paraStackPtr->top] = paraValue;
}
//出栈
char pop(StackPtr paraStackPtr)
{
//判断空栈
if(paraStackPtr->top < 0)
{
printf("空栈,不能删除\r\n");
return '\0';
}
paraStackPtr->top --;
return paraStackPtr->data[paraStackPtr->top + 1];
}
//提取栈顶
int getTop(StackPtr paraStackPtr)
{
//判断空栈
if(paraStackPtr->top < 0)
{
printf("空栈,不能提取\r\n");
return '\0';
}
return paraStackPtr->data[paraStackPtr->top];
}
//应用一:括号匹配
bool bracketMatch(char* paraString,int paraLength)//只有true和false两个返回值
{
//初始化,将#放入栈底
StackPtr tempStack = initStack();
push(tempStack,'#');
char tempChar,tempPopedChar;
for(int i=0;i<paraLength;i++)
{
tempChar = paraString[i];
switch(tempChar)
{
case'(':
case'[':
case'{':
push(tempStack,tempChar);
break;
case')':
tempPopedChar = pop(tempStack);
if(tempPopedChar != '(')
{
return false;
}
break;
case']':
tempPopedChar = pop(tempStack);
if(tempPopedChar != '[')
{
return false;
}
break;
case'}':
tempPopedChar = pop(tempStack);
if(tempPopedChar != '{')
{
return true;
}
break;
default:
break;
}
}
tempPopedChar = pop(tempStack);
if(tempPopedChar != '#')
{
return false;
}
return true;
}
//应用二:多项式的计算
//优先级关系(运用二维数组表示优先级关系,虽然代码繁琐,但是直观明了,不易出错)
char priority(char ch1,char ch2)
{
int i,j;
char pri[7][7]={// + - * / ( ) =
{'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},
{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},
{'<','<','<','<','<','=','0'},
{'>','>','>','>','0','>','>'},
{'<','<','<','<','<','0','='}
};
switch(ch1)
{
case '+': i = 0;
break;
case '-': i = 1;
break;
case '*': i = 2;
break;
case '/': i = 3;
break;
case '(': i = 4;
break;
case ')': i = 5;
break;
case '=': i = 6;
break;
}
switch(ch2)
{
case '+': j = 0;
break;
case '-': j = 1;
break;
case '*': j = 2;
break;
case '/': j = 3;
break;
case '(': j = 4;
break;
case ')': j = 5;
break;
case '=': j = 6;
break;
}
return pri[i][j];
}
//计算
int evaluate(int a,char ch,int b)
{
int result;
switch(ch)
{
case'+':
return a+b;
case'-':
return a-b;
case'*':
return a*b;
case'/':
if(b != 0)
return a/b;
else
{
printf("除数为0,无法计算\n");
}
}
}
//判断运算符和操作符
int judge(char ch)//运算符返回1,操作符返回0
{
switch(ch)
{
case'+':
case'-':
case'*':
case'/':
case'(':
case')':
case'=':
return 1;
default:
return 0;
}
}
//多项式计算
int evaluateExpression(char *paraExpression)
{
StackPtr tempStack1=initStack();//运算数栈
StackPtr tempStack2=initStack();//运算符栈
int a,b,ch,x,x1,x2;//x存放多余出栈元素,x1,x2用于计算
char cha;
int i = 0;
push(tempStack2,'=');//多项式以'='结尾
cha = paraExpression[i++];
while(cha != '=' || getTop(tempStack2) != '=')
{
if(judge(cha))//判断是否为运算符
{
switch(priority(getTop(tempStack2),cha))
{
case'<':
push(tempStack2,cha);
cha = paraExpression[i++];
break;
case'>':
ch = pop(tempStack2);
b = pop(tempStack1);
a = pop(tempStack1);
push(tempStack1,evaluate(a,ch,b));
break;
case'=':
x = pop(tempStack2);
cha = paraExpression[i++];
break;
}
}
else if(isdigit(cha))
{
x1 = cha-'0';
push(tempStack1,x1);
x2 = x1;
cha = paraExpression[i++];
while(isdigit(cha))//判断是否为运算数,是则返回1(存储于ctype.h头文件中)
{
x1 = cha - '0';
x2 = 10*x2 + x1;
x = pop(tempStack1);
push(tempStack1,x2);
cha = paraExpression[i++];
}
}
else if(cha == ' ')
{
while(cha == ' ')
{
cha == paraExpression[i++];
}
}
else
{
printf("多项式错误\n");
}
}
return getTop(tempStack1);
}
//栈的进出测试
void pushPopText()
{
printf("栈进出测试开始:\r\n");
//初始化
StackPtr tempStack = initStack();
printf("初始化后的栈:");
outputStack(tempStack);
//入栈
for(char ch='a';ch<'n';ch++)
{
printf("添加%c:",ch);
push(tempStack,ch);
outputStack(tempStack);
}
//出栈
for(int i=0;i<4;i++)
{
char ch=pop(tempStack);
printf("删除%c:",ch);
outputStack(tempStack);
}
printf("测试结束。\r\n");
printf("\r\n");
}
//括号匹配测试
void bracketMatchText()
{
printf("括号匹配测试开始:\r\n");
char* tempExpression = "{7+2-[4+6*(7-3)]}/3";
bool tempMatch = bracketMatch(tempExpression,17);
printf("‘%s’是否括号匹配? %d\r\n",tempExpression,tempMatch);
tempExpression = "[7-8*6)(]";
tempMatch = bracketMatch(tempExpression,9);
printf("‘%s’是否括号匹配? %d\r\n",tempExpression,tempMatch);
tempExpression = "(()[])";
tempMatch = bracketMatch(tempExpression,6);
printf("‘%s’是否括号匹配? %d\r\n",tempExpression,tempMatch);
tempExpression = "{]()";
tempMatch = bracketMatch(tempExpression,4);
printf("‘%s’是否括号匹配? %d\r\n",tempExpression,tempMatch);
printf("测试结束。\r\n");
printf("\r\n");
}
//多项式计算测试
void evaluateExpressionText()
{
printf("多项式计算测试开始:\n");
int result;
char *tempExpression="7-6*8/2=";
result = evaluateExpression(tempExpression);
printf("%s%d\n",tempExpression,result);
tempExpression="3+6*9=";
result = evaluateExpression(tempExpression);
printf("%s%d\n",tempExpression,result);
tempExpression="7*(4+2)-(3*5)=";
result = evaluateExpression(tempExpression);
printf("%s%d\n",tempExpression,result);
printf("测试结束。\n");
}
int main()
{
pushPopText();
bracketMatchText();
evaluateExpressionText();
}