数据结构—栈的实现及实战应用
2017-06-11 21:46
190 查看
今天主要学习了下栈,下面对所学习到关于栈的知识进行下汇总:
首先,栈是一种特殊的线性表,相对于线性表,栈仅能在一端进行操作,所以在我们的栈的实现过程中,完全可以复用线性表的程序,对其进行封装下,达到能满足我们要求的栈的程序。
下面介绍下栈中的两个概念:
栈顶(Top):允许操作的一端
栈底(Bottom):不允许操作的一端
对于栈的性质,我想接触过计算机基础的同学都知道,先进后出嘛。(LIFO:last in first out)
通常栈有两种实现方式:顺序结构和链式结构
首先来顺序结构栈的一些常用操作(借用顺序线性表的代码直接实现出来):
创建栈
销毁栈
清空栈
进栈
出栈
获取栈顶元素
获取栈的大小
再来借用链式结构表对链式结构栈的常用操作进行实现:
链式结构表的实现:https://code.csdn.net/snippets/2438351.git
实现方式都贴出来了,怎么能少了应用呢。
在我们的学习中,少不了编译器的使用,当然,几乎所有的编译器都具有检测括号是否匹配的功能。下面就用链式结构的栈来实现下编译器中的检测括号功能。
如何实现编译器中的符号成对检测功能,作为个编程人员,必要的算法必不可少,那么编译器检测括号的的算法是怎样的呢,我们来整理下思路:
算法思路:
从第一个字符开始扫描
当遇见普通字符时忽略,当遇见左符号时压入栈中
当遇见右符号时从栈中弹出栈顶符号
进行匹配
匹配成功:继续读入下一个字符
匹配失败:立即停止,并报错
结束:
成功:所有字符扫描完毕,且栈为空
失败:匹配失败或所有字符扫描完毕但栈非空
实现代码如下(链式栈与链式结构的实现都在在上面):
首先,栈是一种特殊的线性表,相对于线性表,栈仅能在一端进行操作,所以在我们的栈的实现过程中,完全可以复用线性表的程序,对其进行封装下,达到能满足我们要求的栈的程序。
下面介绍下栈中的两个概念:
栈顶(Top):允许操作的一端
栈底(Bottom):不允许操作的一端
对于栈的性质,我想接触过计算机基础的同学都知道,先进后出嘛。(LIFO:last in first out)
通常栈有两种实现方式:顺序结构和链式结构
首先来顺序结构栈的一些常用操作(借用顺序线性表的代码直接实现出来):
创建栈
SeqStack* SeqStack_Create(int capacity) { return SeqList_Create(capacity); }
销毁栈
void SeqStack_Destroy(SeqStack* stack) { SeqList_Destroy(stack); }
清空栈
void SeqStack_Clear(SeqStack* Stack) { SeqList_Clear(Stack); }
进栈
int SeqStack_Push(SeqStack* stack,void* item) { return SeqList_Insert(stack,item,SeqList_Length(stack)); }
出栈
void* SeqStack_Pop(SeqStack* stack) { return SeqList_Delete(stack,SeqList_Length(stack) - 1); }
获取栈顶元素
void* SeqStack_Top(SeqStack* stack) { return SeqList_Get(stack,SeqList_Length(stack) - 1); }
获取栈的大小
int SeqStack_Size(SeqStack* stack) { return SeqList_Length(stack); }
再来借用链式结构表对链式结构栈的常用操作进行实现:
链式结构表的实现:https://code.csdn.net/snippets/2438351.git
#include <malloc.h> #include "LinkStack.h" #include "LinkList.h" typedef struct _tag_LinkStack { LinkListNode header; void* item; }TLinkStackNode; LinkStack* LinkStack_Create() { return LinkList_Create(); } void LinkStack_Destroy(LinkStack* stack) { LinkStack_Clear(); LinkList_Destroy(stack); } void LinkStack_Clear(LinkStack* stack) { while( LinkStack_Size(stack) > 0) { LinkStack_Pop(stack); } } int LinkStack_Push(LinkStack* stack,void* item) { TLinkStackNode* node = (TLinkStackNode*)malloc(sizeof(TLinkStackNode)); int ret = (node != NULL) && (item != NULL); if( ret ) { node->item = item; ret = LinkList_Insert(stack,(LinkListNode*)node,0); } if( !ret ) { free(node); } return ret; } void* LinkStack_Pop(LinkStack* stack) { TLinkStackNode* node = (TLinkStackNode*)LinkList_Delete(stack,0); void* ret = NULL; if( node != NULL) { ret = node->item; free(node); } return ret; } void* LinkStack_Top(LinkStack* stack) { TLinkStackNode* node = (TLinkStackNode*)LinkList_Get(stack,0); void* ret = NULL; if( node != NULL) { ret = node->item; } return ret; } int LinkStack_Size(LinkStack* stack) { return LinkList_Length(stack); }
实现方式都贴出来了,怎么能少了应用呢。
在我们的学习中,少不了编译器的使用,当然,几乎所有的编译器都具有检测括号是否匹配的功能。下面就用链式结构的栈来实现下编译器中的检测括号功能。
如何实现编译器中的符号成对检测功能,作为个编程人员,必要的算法必不可少,那么编译器检测括号的的算法是怎样的呢,我们来整理下思路:
算法思路:
从第一个字符开始扫描
当遇见普通字符时忽略,当遇见左符号时压入栈中
当遇见右符号时从栈中弹出栈顶符号
进行匹配
匹配成功:继续读入下一个字符
匹配失败:立即停止,并报错
结束:
成功:所有字符扫描完毕,且栈为空
失败:匹配失败或所有字符扫描完毕但栈非空
实现代码如下(链式栈与链式结构的实现都在在上面):
#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("Invailed code!\n"); ret = 0; } LinkStack_Destroy(stack); return ret; } int main(int argc, char *argv[]) { const char* code = "int main() {int (*p[5],p = NULL;return 0;}"; scanner(code); return 0; }
相关文章推荐
- 数据结构之应用 "栈(Stack)" 实现: 解析算术表达式及计算求值 (C#/Java)
- 实战 linux蓝牙编程之(八) hci 协议 应用编程实现
- js实现双向链表互联网机顶盒实战应用实现
- 【学习点滴-数据结构-栈&队列】 栈的应用--递归的实现-汉诺塔
- 【LeanEAP.NET】精益企业应用平台实战----表格批量编辑与Undo/Redo功能实现
- 数据结构之应用 "栈(Stack)" 实现: 解析算术表达式及计算求值 (C#/Java) (转载)
- 实战 linux蓝牙编程之(八) hci 协议 应用编程实现
- 数据结构—中缀表达式转后缀表达式算法及实现—栈的应用—计算表达式(C++代码实现)(1)
- C#数据结构和算法学习系列七----队列、队列的实现和应用
- 数据结构试验-栈的实现及其应用
- WIF应用与ADFS 2.0配置实战(续):实现SSO
- 数据结构的应用——使用栈实现任意迷宫的求解
- 数据结构的应用——使用栈实现字符串括号匹配检查
- js实现双向链表互联网机顶盒实战应用
- 数据结构学习系列六-链式栈(c++实现且应用模板)
- 实战 linux蓝牙编程之(八) hci 协议 应用编程实现
- 数据结构应用——使用栈实现十进制到其他数制的转换
- 数据结构学习系列三-单向循环链表(c++实现且应用模板)
- (android硬件应用实战)摄像头拍照实现和总结
- [C++]数据结构:散列表HashTable的实现与简单应用