栈与队列的应用

从一张思维导图来进入这块知识。
在这里插入图片描述

栈的应用

进制转换

当一个十进制数N转换成八进制数时,计算过程中,把N与8求余得到的八进制数的各位依次进栈,计算完毕后将栈中的八进制依次出栈,输出结果就是待求得的八进制数。(这里顺序存储和链式存储都可以使用)
下面来看一下它的过程:
1.初始化空栈
2.十进制数N非0时,循环以下操作:
(1)N与8求余,余数入栈;
(2)N更新为N与8的商
3.栈非空时,循环以下操作:
(1)弹出栈顶元素
(2)输出e。
下面是代码实现

void conversion(){
	InitStack(S);//构造空栈
	scanf("%d",&N);
	while(N){
		Push(S,N%8);
		N=N/8;
	}
	while(!StackEmpty(S)){
		Pop(S,e);
		printf("%d",e);
	}
}

括号匹配

借助一个栈,每读入一个左括号,则直接入栈,等待相匹配的右括号;每次读入一个右括号,若与当前栈顶的左括号类型相同,将栈顶中的左括号出栈,直到表达式扫描完毕。
我们来模拟以下这个过程:
比如下面是我们要扫描的括号

{[()]}

第一步:将{入栈
第二步:还是左括号继续入栈
第三步:还是左括号继续入栈,所以现在栈中是{[(
第四步:遇到右括号),发现它与栈顶的左括号匹配,弹出,剩下操作一样。
详细步骤:
1.初始化空栈
2.判断是否有括号未处理(栈空),有则循环以下操作:
(1)左括号则入栈;
(2)栈顶元素出栈,右括号则看跟栈顶元素是否匹配,匹配则继续循环,否则错误匹配跳出循环
3.循环结束,若栈空则匹配成功。
下面是具体的代码实现:

bool bracketCheck(char str[],int length){
	SqStack S;
	InitStack(S);
	for(int i=0;i<length;i++){
		if(str[i]=='(' || str[i]=='[' || str[i]=='{'){
			Push(S,str[i]);//扫描到左括号入栈
		}
		else{
			if(StackEmpty(S)) return false;//扫描到右括号且栈空
			char topElem;
			Pop(S,topElem);//栈顶元素出栈再判断是否匹配
			if(str[i]==')' && topElem!='(')
				return false;
			if(str[i]==']' && topElem!='[')
				return false;
			if(str[i]=='}' && topElem!='{')
				return false;
		}
	}
	return StackEmpty(S);
}

表达式求值

在了解表达式求值前,我们需要先了解几个东西。
比如一个表达式是:b - (a + 5) * 3
那么,如果将它们转换成前缀和后缀,我们这里看到的,或者比如a+b的,我们将它成为中缀表达式,而前缀就是运算符在两个操作数前面,比如:+ab。后缀表达式就是运算符在两个操作符后面,比如ab+。
当运算顺序不唯一,中缀转后缀的表达式也不唯一。
那么我们来举个例子看下一个中缀表达式如何转为后缀表达式。
比如:A+B (C-D)- E/F。
初始化一个运算符栈,用于保存在那时还不能确定运算顺序的运算符。
从左到右处理中缀表达式各个元素,
1.遇到操作符,直接加入后缀表达式
2.遇到界限符"(“直接入栈,遇到”)“则依次弹出栈内运算符并加入后缀表达式,直到弹出”("为止。
3.遇到运算符,依次弹出栈中优先级高于或等于当前运算的所有运算符,并加入后缀表达式。
来模拟一下上面这个式子的过程。
1.一开始是A,所以直接加入后缀表达式,后缀表示内容:A
2.遇到“+”号,加入符号栈。所以符号栈和后缀表达式内容入下图。

3.遇到B加入到后缀表达式。
4.遇到“ * ”,因为“+”的优先级比它低,所以也加入符号栈,现在符号栈和后缀表达式内容如下图。
在这里插入图片描述
5.遇到“(”,加入符号栈。
6.遇到C加入后缀表达式内容
7.遇到“-”,加入符号栈
8.遇到D加入后缀表达式,这时候的符号栈和后缀表达式入下图。
在这里插入图片描述
9.这时候检查到了“)”,所以将“-”出栈加入后缀表达式内容,直到将左括号也出栈。这时候符号栈和后缀表达式内容入下。
在这里插入图片描述
10.这时候遇到了符号“-”,但是符号栈中是“ * ”,所以将“ * ”出栈,并且“+”和“-”是同级,所以“+”也出栈,并且将“-”压入栈。得到符号栈和后缀表达式入下图。
在这里插入图片描述
11.将E放入后缀表达式内容
12.将“/”放入符号栈
13.将F放入后缀表达式内容
14.将符号栈的内容依次弹出得到最终结果。ABCD-
+EF/-

栈的应用——递归

其实递归就是用到了栈。我们先来看一串代码:

void main(){
	int a,b,c;
	func1(a);
}
void func1(int a){
	int x;
	fun2(x);
}
void func2(int x){
	int m,n;
}

这里引入一个概念,函数调用时,最后被调用的函数最先执行结束(LIFO)。比如上面代码,先调用main,那么把main压入栈,main里调用func1,那么把func1压入栈,func1里调用func2,再把func2压入栈。所以得到的栈的图如下:
在这里插入图片描述
有很多用到递归的都是调用了栈,比如计算阶乘,代码如下:

int f(int n){
	if(n==0 || n==1)
		return 1;
	else retur n*f(n-1);
}
int main(){
	int x = f(5);
}

这里把n写的小了点,方便画图操作。那么开始模拟吧。
1.调用f(5),那么把f(5)入栈。
2.f(5)里面调用了f(4),把f(4)入栈。
3.f(4)里面调用了f(3),把f(3)入栈
4.f(3)里面调用了f(2),把f(2)入栈
5.f(2)里面调用了f(1),把f(1)入栈
6.这时候f(1)开始返回。可以看下面这张图。
在这里插入图片描述
所以返回给f(2)后,f(2)=2 * 1,f(2)给f(3)之后,f(3)=3 * 2 * 1,依次返回直到f(5)。所以这样就计算出5的阶乘啦。

队列的应用

队列的应用在思维导图中有三个,树的层次遍历,和图的广度优先,这里就不详述,想要了解可以翻阅我其他关于树和图的文章即可。还有一个操作系统中的应用就是进程争夺临界资源的时候,有一个先来先服务的,比如打印机只有这个人的打印完才能打印下一个的,是需要排队的,需要了解先来先服务的可以去我操作系统相关文章了解。

总结

虽然说这篇文章是说栈与队列的应用,其实上更多,不对是都在讲栈的应用,队列的应用很多出现在其他篇章中,所以可以翻阅其他文章。如果本文中有什么错误或者理解不当的地方,欢迎指出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值