您的位置:首页 > 理论基础 > 数据结构算法

数据结构—栈的实现及实战应用

2017-06-11 21:46 190 查看
今天主要学习了下栈,下面对所学习到关于栈的知识进行下汇总:

首先,栈是一种特殊的线性表,相对于线性表,栈仅能在一端进行操作,所以在我们的栈的实现过程中,完全可以复用线性表的程序,对其进行封装下,达到能满足我们要求的栈的程序。

下面介绍下栈中的两个概念:

栈顶(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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: