单链表堆栈的应用
说明
1、基于Visual Studio 2022环境,用C++实现
2、堆栈是用单链表实现的,堆栈的函数有
//初始化堆栈,带有头结点,头结点指向栈顶
void InitStack(LiStack& L);
//入栈,即头插法插入元素
void push(LiStack& L, ElemType i);
//判断栈是否为空
bool IsEmpty(LiStack L);
//出栈,即删除头结点的后一个结点
bool pop(LiStack& L);
//读栈顶元素,通过x返回值
bool GetTop(LiStack L, ElemType& x);
//销毁整个栈
void DestroyStack(LiStack& L);
3、主要是对堆栈的一些常见应用的实现
4、本人在学习数据结构后,依据算法实现的代码
具体有以下四个应用的实现
1、括号匹配算法
//括号匹配算法,基于堆栈
bool BracketMatching(char str[]) {
LiStack S;
InitStack(S);
char x;
int length = strlen(str);
int i = 0;
for (i = 0; i < length; i++) {
if (str[i] == '(')
push(S, str[i]);
else if (str[i] == ')') {
if (IsEmpty(S))
return false;//此时有右括号,但堆栈为空,匹配失败
GetTop(S, x);
if (x == '(')
pop(S);
else
return false;//左右括号不匹配
}
else
return false;//传入的字符串中除了左右括号还有其他值
}
if (!IsEmpty(S))
return false;//匹配完一轮后,堆栈中仍有左括号,匹配失败
return true;
}
2、堆栈实现中缀表达式转后缀表达式
//栈实现中缀表达式转后缀表达式
bool InfixToExpression(char str[],char result[20]) {
LiStack S;
InitStack(S);
char x = '\0';
int length = strlen(str);
char temp[20]="";
int temp_len = 0;
int i = 0;
for(i=0;i<length;i++){
if (str[i] == '(') {//左括号直接入栈
push(S, str[i]);
}
else if (str[i] == '+') {//为 + 号,弹出 * / + - 运算符
GetTop(S, x);//如果栈空,x则无值,不会进入while
while (x == '*' || x == '/' || x == '-' || x == '+') {
temp[temp_len++] = x;
pop(S);
GetTop(S, x);
}
push(S, str[i]);//弹出需要弹的后,将当前运算符入栈
}
else if (str[i] == '-') {//为 - 号,弹出 * / + - 运算符
GetTop(S, x);
while (x == '*' || x == '/' || x == '+' || x == '-') {
temp[temp_len++] = x;
pop(S);
GetTop(S, x);
}
push(S, str[i]);//弹出需要弹的后,将当前运算符入栈
}
else if (str[i] == '*') {//为 * 号,弹出 * / 运算符
GetTop(S, x);
while (x == '*' || x == '/') {
temp[temp_len++] = x;
pop(S);
GetTop(S, x);
}
push(S, str[i]);//弹出需要弹的后,将当前运算符入栈
}
else if (str[i] == '/') {//为 / 号,弹出 * / 运算符
GetTop(S, x);
while (x == '*' || x == '/') {
temp[temp_len++] = x;
pop(S);
GetTop(S, x);
}
push(S, str[i]);//弹出需要弹的后,将当前运算符入栈
}
else if (str[i] == ')') {//右括号,直接弹出栈中除 ( 的所有的运算符
GetTop(S, x);
while (!IsEmpty(S)) {
if (x == '(') {
pop(S);
break;
}
temp[temp_len++] = x;
pop(S);
GetTop(S, x);
}
}
else if ((str[i] >= 48 && str[i] <= 57)|| (str[i] >= 65 && str[i] <= 90) ) {//为操作数,则直接加在表达式后
temp[temp_len++] = str[i];
}
else {
return false;//字符串中含有非法字符
}
}
while (!IsEmpty(S)) {//最后弹出栈中所有的操作符
GetTop(S, x);
temp[temp_len++] = x;
pop(S);
}
strcpy(result, temp);
return true;
}
3、堆栈实现后缀表达式的计算
//后缀表达式的计算
void EvaluateSuffixExpression(char str[], int& result) {
LiStack S;
InitStack(S);
int length = strlen(str);
int temp = 0;//暂存结果
char x1 = '\0';
char x2 = '\0';
int i = 0;
for (i = 0; i < length; i++) {
if (str[i] >= 48 && str[i] <= 57) {//为操作数,入栈
push(S, str[i]-48);
}
else if (str[i] == '+') {//为操作符,弹出栈顶两个元素进行运算
GetTop(S, x1);
pop(S);
GetTop(S, x2);
pop(S);
temp = x2 + x1;
push(S, temp);//int 转为 char,并压入堆栈
}
else if (str[i] == '-') {//为操作符,弹出栈顶两个元素进行运算
GetTop(S, x1);
pop(S);
GetTop(S, x2);
pop(S);
temp = x2 - x1;
push(S, temp);//int 转为 char,并压入堆栈
}
else if (str[i] == '*') {//为操作符,弹出栈顶两个元素进行运算
GetTop(S, x1);
pop(S);
GetTop(S, x2);
pop(S);
temp = x2 * x1;
push(S, temp);//int 转为 char,并压入堆栈
}
else if (str[i] == '/') {//为操作符,弹出栈顶两个元素进行运算
GetTop(S, x1);
pop(S);
GetTop(S, x2);
pop(S);
temp = x2 / x1;
push(S, temp);//int 转为 char,并压入堆栈
}
}
GetTop(S, x1);
result = x1;
}
4、堆栈直接计算中缀表达式
//辅助函数,根据传入的堆栈和 运算符计算结果
int Calculation(LiStack& S, char x) {
char x1 = '\0';
char x2 = '\0';
int temp = 0;
if (x == '+') {//为操作符,弹出栈顶两个元素进行运算
GetTop(S, x1);
pop(S);
GetTop(S, x2);
pop(S);
temp = x2 + x1;
push(S, temp);//int 转为 char,并压入堆栈
}
else if (x == '-') {//为操作符,弹出栈顶两个元素进行运算
GetTop(S, x1);
pop(S);
GetTop(S, x2);
pop(S);
temp = x2 - x1;
push(S, temp);//int 转为 char,并压入堆栈
}
else if (x == '*') {//为操作符,弹出栈顶两个元素进行运算
GetTop(S, x1);
pop(S);
GetTop(S, x2);
pop(S);
temp = x2 * x1;
push(S, temp);//int 转为 char,并压入堆栈
}
else if (x == '/') {//为操作符,弹出栈顶两个元素进行运算
GetTop(S, x1);
pop(S);
GetTop(S, x2);
pop(S);
temp = x2 / x1;
push(S, temp);//int 转为 char,并压入堆栈
}
GetTop(S, x1);
temp = x1;
return temp;
}
//中缀表达式的计算
void CalculateInfixExpression(char str[], int& result) {
LiStack S;//Symbol Stack
LiStack O;//Operand Stack
InitStack(S);
InitStack(O);
int temp = 0;//暂存结果
int length = strlen(str);
int i = 0;
char x = '\0';
for (i = 0; i < length; i++) {
if (str[i] >= 48 && str[i] <= 57) {//为操作数,压入操作数栈
push(O, str[i] - 48);
}
else if (str[i] == '(') {//左括号直接压入符号栈
push(S, str[i]);
}
else if (str[i] == '+') {//为 + 号,弹出 * / + - 运算符,并进行运算
GetTop(S, x);//如果栈空,x则无值,不会进入while
while (x == '*' || x == '/' || x == '-' || x == '+') {
Calculation(O, x);
pop(S);
GetTop(S, x);
}
push(S, str[i]);//弹出需要弹的后,将当前运算符入栈
}
else if (str[i] == '-') {//为 - 号,弹出 * / + - 运算符
GetTop(S, x);
while (x == '*' || x == '/' || x == '+' || x == '-') {
Calculation(O, x);
pop(S);
GetTop(S, x);
}
push(S, str[i]);//弹出需要弹的后,将当前运算符入栈
}
else if (str[i] == '*') {//为 * 号,弹出 * / 运算符
GetTop(S, x);
while (x == '*' || x == '/') {
Calculation(O, x);
pop(S);
GetTop(S, x);
}
push(S, str[i]);//弹出需要弹的后,将当前运算符入栈
}
else if (str[i] == '/') {//为 / 号,弹出 * / 运算符
GetTop(S, x);
while (x == '*' || x == '/') {
Calculation(O, x);
pop(S);
GetTop(S, x);
}
push(S, str[i]);//弹出需要弹的后,将当前运算符入栈
}
else if (str[i] == ')') {//右括号,直接弹出栈中除 ( 的所有的运算符
GetTop(S, x);
while (!IsEmpty(S)) {
if (x == '(') {
pop(S);
break;
}
Calculation(O, x);
pop(S);
GetTop(S, x);
}
}
}
while (!IsEmpty(S)) {//弹出符号栈中剩余的运算符
GetTop(S, x);
Calculation(O, x);
pop(S);
}
GetTop(O, x);
result = x;
}
整体代码
#include<iostream>
#include<stdio.h>
#include<string.h>
#pragma warning(disable:4996)
typedef char ElemType;
//定义单链表堆栈
typedef struct Linknode {
ElemType date;
struct Linknode* next;
}*LiStack, Linknode;
//初始化堆栈,带有头结点,头结点指向栈顶
void InitStack(LiStack& L) {
LiStack Lnode = (LiStack)malloc(sizeof(Linknode));
Lnode->date = 0;
Lnode->next = NULL;
L = Lnode;
}
//入栈,即头插法插入元素
void push(LiStack& L, ElemType i) {
LiStack p = (LiStack)malloc(sizeof(Linknode));
p->date = i;
p->next = L->next;
L->next = p;
}
//判断栈是否为空
bool IsEmpty(LiStack L) {
if (L->next == NULL)
return true;
return false;
}
//出栈,即删除头结点的后一个结点
bool pop(LiStack& L) {
if (IsEmpty(L))
return false;
LiStack p = L->next;
L->next = p->next;
free(p);
}
//读栈顶元素,通过x返回值
bool GetTop(LiStack L, ElemType& x) {
if (IsEmpty(L)) {
x = '\0';//栈空,x无值
return false;
}
x = L->next->date;
return true;
}
//销毁整个栈
void DestroyStack(LiStack& L) {
LiStack p = L;
if (p->next == NULL) {
free(p);
return;
}
LiStack q = p->next;
while (q != NULL) {
free(p);
p = q;
q = p->next;
}
return;
}
//括号匹配算法,基于堆栈
bool BracketMatching(char str[]) {
LiStack S;
InitStack(S);
char x;
int length = strlen(str);
int i = 0;
for (i = 0; i < length; i++) {
if (str[i] == '(')
push(S, str[i]);
else if (str[i] == ')') {
if (IsEmpty(S))
return false;//此时有右括号,但堆栈为空,匹配失败
GetTop(S, x);
if (x == '(')
pop(S);
else
return false;//左右括号不匹配
}
else
return false;//传入的字符串中除了左右括号还有其他值
}
if (!IsEmpty(S))
return false;//匹配完一轮后,堆栈中仍有左括号,匹配失败
return true;
}
//栈实现中缀表达式转后缀表达式
bool InfixToExpression(char str[],char result[20]) {
LiStack S;
InitStack(S);
char x = '\0';
int length = strlen(str);
char temp[20]="";
int temp_len = 0;
int i = 0;
for(i=0;i<length;i++){
if (str[i] == '(') {//左括号直接入栈
push(S, str[i]);
}
else if (str[i] == '+') {//为 + 号,弹出 * / + - 运算符
GetTop(S, x);//如果栈空,x则无值,不会进入while
while (x == '*' || x == '/' || x == '-' || x == '+') {
temp[temp_len++] = x;
pop(S);
GetTop(S, x);
}
push(S, str[i]);//弹出需要弹的后,将当前运算符入栈
}
else if (str[i] == '-') {//为 - 号,弹出 * / + - 运算符
GetTop(S, x);
while (x == '*' || x == '/' || x == '+' || x == '-') {
temp[temp_len++] = x;
pop(S);
GetTop(S, x);
}
push(S, str[i]);//弹出需要弹的后,将当前运算符入栈
}
else if (str[i] == '*') {//为 * 号,弹出 * / 运算符
GetTop(S, x);
while (x == '*' || x == '/') {
temp[temp_len++] = x;
pop(S);
GetTop(S, x);
}
push(S, str[i]);//弹出需要弹的后,将当前运算符入栈
}
else if (str[i] == '/') {//为 / 号,弹出 * / 运算符
GetTop(S, x);
while (x == '*' || x == '/') {
temp[temp_len++] = x;
pop(S);
GetTop(S, x);
}
push(S, str[i]);//弹出需要弹的后,将当前运算符入栈
}
else if (str[i] == ')') {//右括号,直接弹出栈中除 ( 的所有的运算符
GetTop(S, x);
while (!IsEmpty(S)) {
if (x == '(') {
pop(S);
break;
}
temp[temp_len++] = x;
pop(S);
GetTop(S, x);
}
}
else if ((str[i] >= 48 && str[i] <= 57)|| (str[i] >= 65 && str[i] <= 90) ) {//为操作数,则直接加在表达式后
temp[temp_len++] = str[i];
}
else {
return false;//字符串中含有非法字符
}
}
while (!IsEmpty(S)) {//最后弹出栈中所有的操作符
GetTop(S, x);
temp[temp_len++] = x;
pop(S);
}
strcpy(result, temp);
return true;
}
//后缀表达式的计算
void EvaluateSuffixExpression(char str[], int& result) {
LiStack S;
InitStack(S);
int length = strlen(str);
int temp = 0;//暂存结果
char x1 = '\0';
char x2 = '\0';
int i = 0;
for (i = 0; i < length; i++) {
if (str[i] >= 48 && str[i] <= 57) {//为操作数,入栈
push(S, str[i]-48);
}
else if (str[i] == '+') {//为操作符,弹出栈顶两个元素进行运算
GetTop(S, x1);
pop(S);
GetTop(S, x2);
pop(S);
temp = x2 + x1;
push(S, temp);//int 转为 char,并压入堆栈
}
else if (str[i] == '-') {//为操作符,弹出栈顶两个元素进行运算
GetTop(S, x1);
pop(S);
GetTop(S, x2);
pop(S);
temp = x2 - x1;
push(S, temp);//int 转为 char,并压入堆栈
}
else if (str[i] == '*') {//为操作符,弹出栈顶两个元素进行运算
GetTop(S, x1);
pop(S);
GetTop(S, x2);
pop(S);
temp = x2 * x1;
push(S, temp);//int 转为 char,并压入堆栈
}
else if (str[i] == '/') {//为操作符,弹出栈顶两个元素进行运算
GetTop(S, x1);
pop(S);
GetTop(S, x2);
pop(S);
temp = x2 / x1;
push(S, temp);//int 转为 char,并压入堆栈
}
}
GetTop(S, x1);
result = x1;
}
//辅助函数,根据传入的堆栈和 运算符计算结果
int Calculation(LiStack& S, char x) {
char x1 = '\0';
char x2 = '\0';
int temp = 0;
if (x == '+') {//为操作符,弹出栈顶两个元素进行运算
GetTop(S, x1);
pop(S);
GetTop(S, x2);
pop(S);
temp = x2 + x1;
push(S, temp);//int 转为 char,并压入堆栈
}
else if (x == '-') {//为操作符,弹出栈顶两个元素进行运算
GetTop(S, x1);
pop(S);
GetTop(S, x2);
pop(S);
temp = x2 - x1;
push(S, temp);//int 转为 char,并压入堆栈
}
else if (x == '*') {//为操作符,弹出栈顶两个元素进行运算
GetTop(S, x1);
pop(S);
GetTop(S, x2);
pop(S);
temp = x2 * x1;
push(S, temp);//int 转为 char,并压入堆栈
}
else if (x == '/') {//为操作符,弹出栈顶两个元素进行运算
GetTop(S, x1);
pop(S);
GetTop(S, x2);
pop(S);
temp = x2 / x1;
push(S, temp);//int 转为 char,并压入堆栈
}
GetTop(S, x1);
temp = x1;
return temp;
}
//中缀表达式的计算
void CalculateInfixExpression(char str[], int& result) {
LiStack S;//Symbol Stack
LiStack O;//Operand Stack
InitStack(S);
InitStack(O);
int temp = 0;//暂存结果
int length = strlen(str);
int i = 0;
char x = '\0';
for (i = 0; i < length; i++) {
if (str[i] >= 48 && str[i] <= 57) {//为操作数,压入操作数栈
push(O, str[i] - 48);
}
else if (str[i] == '(') {//左括号直接压入符号栈
push(S, str[i]);
}
else if (str[i] == '+') {//为 + 号,弹出 * / + - 运算符,并进行运算
GetTop(S, x);//如果栈空,x则无值,不会进入while
while (x == '*' || x == '/' || x == '-' || x == '+') {
Calculation(O, x);
pop(S);
GetTop(S, x);
}
push(S, str[i]);//弹出需要弹的后,将当前运算符入栈
}
else if (str[i] == '-') {//为 - 号,弹出 * / + - 运算符
GetTop(S, x);
while (x == '*' || x == '/' || x == '+' || x == '-') {
Calculation(O, x);
pop(S);
GetTop(S, x);
}
push(S, str[i]);//弹出需要弹的后,将当前运算符入栈
}
else if (str[i] == '*') {//为 * 号,弹出 * / 运算符
GetTop(S, x);
while (x == '*' || x == '/') {
Calculation(O, x);
pop(S);
GetTop(S, x);
}
push(S, str[i]);//弹出需要弹的后,将当前运算符入栈
}
else if (str[i] == '/') {//为 / 号,弹出 * / 运算符
GetTop(S, x);
while (x == '*' || x == '/') {
Calculation(O, x);
pop(S);
GetTop(S, x);
}
push(S, str[i]);//弹出需要弹的后,将当前运算符入栈
}
else if (str[i] == ')') {//右括号,直接弹出栈中除 ( 的所有的运算符
GetTop(S, x);
while (!IsEmpty(S)) {
if (x == '(') {
pop(S);
break;
}
Calculation(O, x);
pop(S);
GetTop(S, x);
}
}
}
while (!IsEmpty(S)) {//弹出符号栈中剩余的运算符
GetTop(S, x);
Calculation(O, x);
pop(S);
}
GetTop(O, x);
result = x;
}
int main() {
/* 括号匹配
char str[] = "(()()()(())";
if (BracketMatching(str))
printf("匹配成功!");
else
printf("匹配失败!");*/
//中缀转后缀
char str[] = "1+2*3-4/2";//转换结果:123*+42/- 计算结果:5
char str1[] = "1*(8-2+3*2)/3*5";//转换结果:124+*3/5* 计算结果:20
char str2[] = "A+B*(C-D)-E/F";//转换结果:ABCD-*+EF/-
char str3[] = "(3+5*4/2+2*(1+1)*(2+2))";//转换结果:354*2/+211+*22+*+ 计算结果:29
char result[20] = "";
if (InfixToExpression(str3, result)) {
printf("转化的后缀表达式为:%s\n",result);
}
else
printf("转化失败!");
//直接计算中缀表达式
int result2 = 0;
CalculateInfixExpression(str3, result2);
printf("%s 的 直接 计算结果为 :%d\n", str3, result2);
//计算后缀表达式
int result1 = 0;
EvaluateSuffixExpression(result, result1);
printf("%s 的 间接 结果为 :%d\n", result, result1);
return 0;
}
注意:
1、代码为自己手敲代码;
2、有错误或更好的办法欢迎留言评论;
3、若有侵犯个人或团体的权益请及时联系我;
4、本文为原创,转载或引用请注明出处
本文作者:逍遥子
本文连接: https://www.cnblogs.com/femme/p/16418836.html
版权:本人个人所有