ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

单链表堆栈的应用

2022-06-28 11:33:25  阅读:212  来源: 互联网

标签:单链 return 应用 int char LiStack str 堆栈


说明

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

版权:本人个人所有

标签:单链,return,应用,int,char,LiStack,str,堆栈
来源: https://www.cnblogs.com/femme/p/16418836.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有