栈和队列的应用
3.1栈在括号匹配中的应用
用栈实现括号匹配:依次扫描所有字符,遇到左括号入栈,遇到右括号,则弹出栈顶元素,检查是否匹配。
匹配失败情况有:(1)左括号单;(2)右括号单(3)左右括号不匹配
int Match(char c1, char c2) { if ((c1 == '(' && c2 == ')') || (c1 == '[' && c2 == ']') || (c1 == '{' && c2 == '}')) return 1; else return 0; } void BracketMatch(char* str) { SqStack S; int i; char ch; InitStack(&S); for (i = 0; str[i] != '/0'; i++) { switch (str[i]) { case '(': case '[': case '{': Push(&S, str[i]); break; case ')': case ']': case '}': if (IsEmptyStack(S)) { printf("右括号多余!"); return; } else { GetTop(&S, &ch); if (Match(ch, str[i])) Pop(&S, &ch); else { printf("左右括号不匹配"); return; } } } } if (IsEmptyStack(S)) { printf("括号匹配"); } else { printf("右括号多余"); } }
3.2栈在表达式求值中的应用
中缀表达式转后缀表达式:初始化一个栈,用于保存暂时还不能确定运算顺序的运算符,从左到右处理各个元素,直到末尾,可能遇到三种情况:
(1)遇到操作数,直接加入后缀表达式;
(2)遇到界限符,遇到'('直接入栈,遇到')',则依次弹出栈内运算符并加入后缀表达式,直到弹出'('为止【括号不加入后缀表达式】
(3)遇到运算符,此次弹出栈中优先级高于或等于当前运算符的所有运算符,并加入后缀表达式,若碰到'('或栈空则停止。之后再把当前运算符入栈
按上述方法处理完所有字符后,将栈中剩余运算符依次弹出,并加入后缀表达式。
3.3栈在递归中的应用
递归进层(i->i+1层)系统需要做三件事:
(1)保留本层参数与返回地址(2)为被调用函数的局部变量分配存储区,给下层参数赋值(3)将程序转移到被调函数的入口
递归退层(i<-i+1)系统完成的三件工作:
(1)保存被调函数的计算结果(2)释放被调函数的数据区,恢复上层参数(3)依照被调函数保存的返回地址,将控制转移回调用函数
当递归函数调用时,应按照“后调用先返回”的原则处理调用过程,因此上述函数之间的信息传递和控制转移必须通过栈来实现。系统将整
个程序运行时所需的数据空间安排在一个栈中,每当调用一个函数时,就为它在栈顶分配一个存储区,而每当从一个函数退出时,就释放
它的存储区。显然,当前正在运行的函数的数据区必在栈顶。
递归算法的缺点:(1)递归次数过多容易造成栈溢出(2)效率较低,调用过程中包含很多重复的计算
如何消除递归:(1)简单问题递归的转换,对于尾递归和单向递归的算法,可用循环结构的算法代替
(2)利用自定义栈来模拟系统栈。基于栈的方式,即将递归中隐含的栈机制转换为由用户直接控制的明显的栈。利用栈来保存参数
3.4队列在层次遍历中的应用
(1)根节点入队
(2)若队空(所有结点都已处理完毕),则结束遍历;否则重复(3)操作
(3)队列中第一个结点出队,并访问之。若其有左孩子,则将左孩子入队,若其有右孩子,则将右孩子入队,返回(2)
3.5队列在计算机系统中的应用
(1)解决主机与外部设备之间速度不匹配的问题(2)解决由多用户引起的资源竞争问题。

浙公网安备 33010602011771号