5--栈

来源:互联网 发布:linux中拷贝目录命令 编辑:程序博客网 时间:2024/05/16 11:40

Stack基本概念

栈是一种特殊的线性表,也就是具有线性关系,即前驱后继关系。只不过它是一种特殊的线性表而已。又称为后进先出LIFO(Last In First Out)或先进后出(First In First Out)线性表。定义中说在线性表的表尾进行插入和删除操作,这里表尾是指栈顶,而不是栈底。

栈仅能在线性表的一端进行操作

栈顶(Top):允许操作的一端

栈底(Bottom):不允许操作的一端

它的特殊之处就是在与限制了这个线性表的插入和删除位置,它始终只在栈顶进行,也就是:栈顶是固定的,最先进栈的只能在栈底。

栈的插入操作,叫做进栈,也叫压栈、入栈。

栈的删除操作,叫做出栈,也叫弹栈。



Stack的常用操作

创建栈

销毁栈

清空栈

进栈

出栈

获取栈顶元素

获取栈的大小


#ifndef _MY_STACK_H_#define _MY_STACK_H_ typedef void Stack; Stack* Stack_Create(); void Stack_Destroy(Stack* stack); void Stack_Clear(Stack* stack); int Stack_Push(Stack* stack, void* item); void* Stack_Pop(Stack* stack); void* Stack_Top(Stack* stack); int Stack_Size(Stack* stack); #endif//_MY_STACK_H_

#include "stdlib.h"#include "stdio.h"#include "string.h"#include "linkstack.h"#include "linklist.h"typedef struct _tag_LinkStackNode{ LinkListNode node; void *item;}TLinkStackNode;LinkStack* LinkStack_Create(){ return LinkList_Create();}void LinkStack_Destroy(LinkStack* stack){ LinkStack_Clear(stack); LinkList_Destroy(stack); return ;}void LinkStack_Clear(LinkStack* stack){ while (LinkStack_Size(stack) > 0) {  LinkStack_Pop(stack); } return ;}int LinkStack_Push(LinkStack* stack, void* item){ int ret = 0; TLinkStackNode *node = (TLinkStackNode *)malloc(sizeof(TLinkStackNode)); if (node == NULL || item == NULL) {  return -1; } node->item = item; ret = LinkList_Insert(stack, (LinkListNode*)node, 0); if (ret != 0) {  free(node); } return ret;}void* LinkStack_Pop(LinkStack* stack){ void *ret = NULL; TLinkStackNode *node = NULL; if (stack == NULL) {  return NULL; } node = (TLinkStackNode *)LinkList_Delete(stack, 0); if (node == NULL) {  return NULL; } ret = node->item; //注意 释放内存不要忘记 if (node != NULL) {  free(node); } return ret;}void* LinkStack_Top(LinkStack* stack){ void *ret = NULL; TLinkStackNode *node = NULL; if (stack == NULL) {  return NULL; } node = (TLinkStackNode *)LinkList_Get(stack, 0); if (node == NULL) {  return NULL; } ret = node->item; return ret;}int LinkStack_Size(LinkStack* stack){ return LinkList_Length(stack);}

应用1:就近匹配

几乎所有的编译器都具有检测括号是否匹配的能力

如何实现编译器中的符号成对检测?

#include<stdio.h>int main() { int a[4][4]; int (*p)[4]; p = a[0]; return 0;


算法思路

从第一个字符开始扫描

当遇见普通字符时忽略,当遇见左符号时压入栈中

当遇见右符号时从栈中弹出栈顶符号,并进行匹配

匹配成功:继续读入下一个字符

匹配失败:立即停止,并报错

结束:

成功所有字符扫描完毕,且栈为空

失败:匹配失败或所有字符扫描完毕但栈非空

#include "stdio.h"#include "stdlib.h"#include "linkstack.h"int isLeft(char c){ int ret = 0; switch(c) { case '<': case '(': case '[': case '{': case '\'': case '\"':  ret = 1;  break; default:  ret = 0;  break; } return ret;}int isRight(char c){ int ret = 0; switch(c) { case '>': case ')': case ']': case '}': case '\'': case '\"':  ret = 1;  break; default:  ret = 0;  break; } return ret;}int match(char left, char right){ int ret = 0; switch(left) { case '<':  ret = (right == '>');  break; case '(':  ret = (right == ')');  break; case '[':  ret = (right == ']');  break; case '{':  ret = (right == '}');  break; case '\'':  ret = (right == '\'');  break; case '\"':  ret = (right == '\"');  break; default:  ret = 0;  break; } return ret;}int scanner(const char* code){ LinkStack* stack = LinkStack_Create(); int ret = 0; int i = 0; while( code[i] != '\0' ) {  if( isLeft(code[i]) )  {   LinkStack_Push(stack, (void*)(code + i));  }  if( isRight(code[i]) )  {   char* c = (char*)LinkStack_Pop(stack);   if( (c == NULL) || !match(*c, code[i]) )   {    printf("%c does not match!\n", code[i]);    ret = 0;    break;   }  }  i++; } if( (LinkStack_Size(stack) == 0) && (code[i] == '\0') ) {  printf("Succeed!\n");  ret = 1; } else {  printf("Invalid code!\n");  ret = 0; } LinkStack_Destroy(stack); return ret;}void main(){ const char* code = "#include <stdio.h> int main() { int a[4][4]; int (*p)[4]; p = a[0]; return 0;"; scanner(code); system("pause"); return ;}

应用2:中缀后缀

计算机的本质工作就是做数学运算,那计算机可以读入字符串

9 + (3 - 1) * 5 + 8 / 2”并计算值吗?

后缀表达式  ==?符合计算机运算

波兰科学家在20世纪50年代提出了一种将运算符放在数字后面的后缀表达式对应的,

我们习惯的数学表达式叫做中缀表达式===》符合人类思考习惯

实例:

5 + 4=> 5 4 +

1 + 2 * 3 => 1 2 3 * +

8 + ( 3 – 1 ) * 5 => 8 3 1 – 5 * +

中缀表达式符合人类的阅读和思维习惯

后缀表达式符合计算机的“运算习惯”

如何将中缀表达式转换成后缀表达式?


中缀转后缀算法:

遍历中缀表达式中的数字和符号

对于数字:直接输出

对于符号:

左括号:进栈 

运算符号:与栈顶符号进行优先级比较

若栈顶符号优先级低:此符合进栈  (默认栈顶若是左括号,左括号优先级最低)

若栈顶符号优先级不低:将栈顶符号弹出并输出,之后进栈

右括号:将栈顶符号弹出并输出,直到匹配左括号

遍历结束:将栈中的所有符号弹出并输出

中缀转后缀









0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 感觉被南通蒲公英店铺骗了怎么办 6个月宝宝吃米粉不吃奶怎么办 十个月的宝宝不吃辅食怎么办 5个月宝宝拉肚子有泡沫怎么办 生完孩子后皮肤暗黄怎么办 开服装店批发服装的吊牌怎么办 天虹的鞋一天就坏了怎么办 车被钥匙划了露底漆了怎么办 数控铣z轴回不了参考点怎么办 白色衣服被黑色衣服染了怎么办 夏天出汗衣服粘身上都是毛毛怎么办 支付宝租的手机坏了怎么办 新买的衣服布料扎人怎么办 洗衣服的时候卫生纸沾裤子上怎么办 洗衣服给白衣服染上色了怎么办 不小心喝了游泳池的水怎么办 铁水中硅的含量高了怎么办 视频拍摄单人变双人是怎么办的 四季青进来的货比淘宝还贵怎么办 淘宝还没收货价格买贵了怎么办 在微信上赌博庄跑了怎么办 微信赌博输了10000多怎么办 欠了信用卡说来来家里调查怎么办 没用过的超市购物卡丢了怎么办 体验服抢号成功手机号填错了怎么办 起亚kx3一键启动钥匙没电怎么办 逆战下载的时候显示文件损坏怎么办 移动公司买手机送话费套路怎么办 开通京东白条身份信息被占用怎么办 丰巢快递柜把东西寄丢了怎么办? 圆通快递把我寄的东西弄丢了怎么办 快递把我寄出去的东西弄丢了怎么办 京东被盗刷都是到付怎么办 订机票时护照号错了怎么办 请问网上不小心点了扣话费了怎么办 不小心被中国移动扣了话费怎么办 京东买东西已经付款了说无货怎么办 不小心提交了两次中信信用卡怎么办 淘宝买东西扣了银行卡两次钱怎么办 拼多多同一个订单支付了两次怎么办 京东手机号服务密码忘记了怎么办