一:定义
栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。
二:基本操作
1.代码
定义
typedef struct charStack{
int top;
int data[STACK_MAX_SIZE];
}*CharStackPtr;
初始化
CharStackPtr charStackTnit() {
CharStackPtr resultPtr = (CharStackPtr)malloc(sizeof(CharStack));
resultPtr->top = -1;
return resultPtr;
}
打印
void outputStack(CharStackPtr paraStack){
for(int i = 0;i<=paraStack->top;i ++){
printf("%c",paraStack->data[i]);
}
printf("\r\n");
}
入栈
void push(CharStackPtr paraStackPtr,int paraValue){
if(paraStackPtr->top >= STACK_MAX_SIZE - 1){
printf("Cannot push element:stack full.\r\n");
return;
}
paraStackPtr->top ++;
paraStackPtr->data[paraStackPtr->top] = paraValue;
}
出栈
char pop(CharStackPtr paraStackPtr){
if(paraStackPtr->top < 0){
printf("Cannot pop element: stack empty.\r\n");
return 0;
}
paraStackPtr->top --;
return paraStackPtr->data[paraStackPtr->top + 1];
}
测试
void pushPopTest(){
printf("----pushPopTest begins.----\r\n");
CharStackPtr tempStack = charStackInit();
printf("After initialization,the stack is: ");
outputStack(tempStack);
for(char 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);
printf("Pop %c.\r\n",ch);
outputStack(tempStack);
}
printf("---pushPopTest ends.---\r\n");
}
结果
---- pushPopTest begins. ----
After initialization, the stack is:
Pushing a.
a
Pushing b.
a b
Pushing c.
a b c
Pushing d.
a b c d
Pushing e.
a b c d e
Pushing f.
a b c d e f
Pushing g.
a b c d e f g
Pushing h.
a b c d e f g h
Pushing i.
a b c d e f g h i
Pushing j.
a b c d e f g h i j
Pushing k.
Cannot push element: stack full.
a b c d e f g h i j
Pushing l.
Cannot push element: stack full.
a b c d e f g h i j
Pop j.
a b c d e f g h i
Pop i.
a b c d e f g h
Pop h.
a b c d e f g
---- pushPopTest ends. ----
Press any key to continue
三:括号匹配
bool bracketMatching(char* paraString, int paraLength) {
CharStackPtr tempStack = charStackInit();
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 false;
}
break;
default:
break;
}
}
tempPopedChar = pop(tempStack);
if (tempPopedChar != '#') {
return true;
} // Of if
return true;
}
测试
void bracketMatchingTest() {
char* tempExpression = "[2 + (1 - 3)] * 4";
bool tempMatch = bracketMatching(tempExpression, 17);
printf("Is the expression '%s' bracket matching? %d \r\n", tempExpression, tempMatch);
tempExpression = "( ) )";
tempMatch = bracketMatching(tempExpression, 6);
printf("Is the expression '%s' bracket matching? %d \r\n", tempExpression, tempMatch);
tempExpression = "()()(())";
tempMatch = bracketMatching(tempExpression, 8);
printf("Is the expression '%s' bracket matching? %d \r\n", tempExpression, tempMatch);
tempExpression = "({}[])";
tempMatch = bracketMatching(tempExpression, 6);
printf("Is the expression '%s' bracket matching? %d \r\n", tempExpression, tempMatch);
tempExpression = ")(";
tempMatch = bracketMatching(tempExpression, 2);
printf("Is the expression '%s' bracket matching? %d \r\n", tempExpression, tempMatch);
}
结果
Is the expression '[2 + (1 - 3)] * 4' bracket matching? 1
Is the expression '( ) )' bracket matching? 0
Is the expression '()()(())' bracket matching? 1
Is the expression '({}[])' bracket matching? 1
Is the expression ')(' bracket matching? 0
Press any key to continue
四:表达式求值
代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <stack>
#include <unordered_map>
using namespace std;
stack<int> num;
stack<char>op;
void eval()
{
auto b = num.top();
num.pop();
auto a = num.top();
num.pop();
auto c = op.top();
op.pop();
int x;
if(c == '+')x = a+b;
else if(c =='-') x = a-b;
else if(c =='*') x = a*b;
else x = a/b;
num.push(x);
}
int main()
{
unordered_map<char,int>pr{{'+', 1},{'-', 1},{'*', 2},{'/', 2}};
string str;
cin >> str;
for(int i = 0; i < str.size(); i ++)
{
auto c = str[i];
if(isdigit(c))
{
int x = 0,j = i;
while (j < str.size() && isdigit(str[j]))
x = x*10 + str[j ++] - '0';
i = j-1;
num.push(x);
}
else if(c == '(') op.push(c);
else if(c == ')')
{
while (op.top() != '(') eval();
op.pop();
}
else
{
while(op.size() && op.top() != '(' && pr[op.top] >= pr[c]) eval();
op.push(c);
}
}
while (op.size()) eval();
cout << num.top() << end1;
return 0;
}
图示
总结:
算法思想
首先,创建一个栈,然后开始读取括号序列(字符串)。
(1)若读入的是左括号,则直接入栈,等待相匹配的同类右括号。
(2)若读入的是右括号,此时应当判断栈是否为空,若栈空,则括号匹配失败,程序结束,返回0;否则,与当前栈顶左括号进行比较,如果二者匹配,将栈顶左括号出栈,继续读取括号序列,如果二者不匹配,则程序结束,返回0。
(3)若输入的括号序列已经读完,则需要判断栈是否为空,若栈空,说明所有的括号完全匹配,程序结束,返回1;否则说明栈中还有等待匹配的左括号,匹配失败,程序结束,返回0