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 * +
中缀表达式符合人类的阅读和思维习惯
后缀表达式符合计算机的“运算习惯”
如何将中缀表达式转换成后缀表达式?
遍历中缀表达式中的数字和符号
对于数字:直接输出
对于符号:
左括号:进栈
运算符号:与栈顶符号进行优先级比较
若栈顶符号优先级低:此符合进栈 (默认栈顶若是左括号,左括号优先级最低)
若栈顶符号优先级不低:将栈顶符号弹出并输出,之后进栈
右括号:将栈顶符号弹出并输出,直到匹配左括号
遍历结束:将栈中的所有符号弹出并输出
中缀转后缀
- 5--栈
- 数据结构(5)--栈
- 5_栈
- 栈-数据结构(5)
- 例题5-5 集合栈计算机 UVa12096
- 数据结构5(链式栈)
- 算法速成(5)栈
- 数据结构5 用一个栈实现另一个栈的排序
- Linux TCP/IP协议栈笔记(5)
- 堆和栈的区别 5
- 数据结构学习笔记5(栈)
- Linux协议栈-netfilter(5)-iptables
- 【5】用两个栈实现队列
- jvm 5块内存 堆,栈等
- 【数据结构学习5】栈的学习
- 第五周项目5-后缀表达式(栈)!!!
- 5、用两个栈实现队列
- 数据结构 第5讲 顺序栈
- XSL 语言(EXtensible Stylesheet Language)
- 图像处理与机器视觉网络资源收罗——倾心大放送
- 白领夫妇卖房回乡 卖掉深圳一套房回武汉换了4套学区房
- 处窥设计模式(1)
- Apple的App Analytics统计平台你必须知道的
- 5--栈
- Thinkphp中事物无效的原因
- 使用getopt 解析参数
- Android 消息机制
- zzulioj 1879: 蛤玮买好了礼物 (gcd)水
- java BufferedReader和BufferedWriter
- python 安装lxml失败
- error:export LD_LIBRARY_PATH is not a known library type
- GEEK编程练习— —旋转排序数组中的查找