1、栈的定义
- 栈是一种特殊的线性表
- 栈仅能在线性表的一端进行操作
- 栈顶( Top ):允许操作的一端
- 栈底( Bottom ): 不允许操作的一端
2、栈的性质
性质:后进先出(LIFO)
3、栈的顺序存储实现
3.1 代码复用
利用【一】线性表的顺序存储结构 中已经实现的线性表,实现顺序存储的栈
完整代码下载:
文件名:seqstack-1.0.tar.gz
链接: http://pan.baidu.com/s/1i31orYH 密码: uu4x
编译步骤:
0.1 解压缩:tar -zxvf seqstack-1.0.tar.gz
0.2 进入目录:./configure
0.3 生成Seqlist:make
0.4 运行程序:./Seqstack
3.2 自己动手实现顺序存储栈
相关数据结构的定义
/*
对外的数据封装,SeqStackNode用于存放指针
*/
typedef void SeqStack;
typedef void SeqStackNode;
内部实现的数据结构定义
/*
解决Windows 和 Linux的差异
*/
#ifdef WIN32
typedef unsigned int TSeqStackNode;
#else
typedef unsigned long TSeqStackNode;
#endif
/*
TSeqStackNode *stack; 成员指向了一个保存指针值的TSeqStackNode类型数组
*/
typedef struct _struct_seqstack
{
int capacity;
int length;
TSeqStackNode *stack;
}TSeqStack;
创建栈操作
/*
创建一个栈
如果成功返回栈的指针,失败返回NULL
capacity 用于指定栈的最大容量
*/
SeqStack* SeqStack_Create(int capacity)
{
TSeqStack *tstack = NULL;
if(capacity > 0)
{
tstack = (TSeqStack*)malloc(sizeof(TSeqStack) +
sizeof(TSeqStackNode) * capacity);
}
if(tstack != NULL)
{
tstack->capacity = capacity;
tstack->length = 0;
tstack->stack = (TSeqStackNode*)(tstack + 1);
}
return tstack;
}
入栈操作
*
往栈中压入数据结点
如果成功,返回非0值,失败,返回0值
*/
int SeqStack_Push(SeqStack* stack, SeqStackNode* item)
{
int iret = 1;
TSeqStack *tstack = (TSeqStack*)stack;
iret = iret && (tstack != NULL) && (item != NULL);
if(iret)
{
int length = tstack->length;
//判断是否还有空间插入元素
iret = iret && (length < tstack->capacity);
if(iret)
{
tstack->stack[length] = (TSeqStackNode)item;
tstack->length++;
}
}
return iret;
}
出栈操作
/*
从栈顶弹出数据结点,并从栈中移出该结点
如果成功,返回该结点指针,失败返回NULL
*/
SeqStackNode* SeqStack_Pop(SeqStack* stack)
{
TSeqStackNode *ret = NULL;
TSeqStack *tstack = (TSeqStack*)stack;
if(tstack != NULL)
{
int pos = tstack->length - 1;
if(pos >= 0)
{
ret = (TSeqStackNode*)tstack->stack[pos];
tstack->length--;
}
}
return ret;
}
完整代码下载:
文件名:seqstack-2.0.tar.gz
链接: http://pan.baidu.com/s/1dDgxHXf 密码: ach3
编译步骤:
0.1 解压缩:tar -zxvf seqstack-2.0.tar.gz
0.2 进入目录:./configure
0.3 生成Seqlist:make
0.4 运行程序:./Seqstack
4、栈的链式存储实现
4.1 代码复用
利用【二】线性表的链式存储结构 中已有的链表代码,实现栈的链式存储结构。
数据结构的定义
/*
对外的数据封装,SeqStackNode用于存放指针
*/
typedef void LinkStack;
typedef void LinkStackNode;
/*
为了让链式存储结构的栈和顺序存储结构的栈在使用上大致相同,
所以再次做一个数据封装,因为底层实现使用的是链式结构的顺序表,
而在顺序表中,插入的数据项类似于如下的结构体;
这里的实现机制是:用户传入要被压入栈的数据元素地址,在内部的实现函数中构造TLinkStackNode结构,然后再传入到线性表的链式存储实现代码中处理
*/
typedef struct _struct_linkstacknode
{
LinklistNode node;
LinkStackNode *item;
}TLinkStackNode;
相关操作的实现
/*
创建一个栈
如果成功返回栈的指针,失败返回NULL
capacity 用于指定栈的最大容量
*/
LinkStack* LinkStack_Create(int capacity)
{
return List_Create();
}
/*
销毁一个栈
*/
void LinkStack_Destroy(LinkStack* stack)
{
LinkStack_Clear(stack);
List_Destroy(stack);
}
/*
清空一个栈
*/
void LinkStack_Clear(LinkStack* stack)
{
while(LinkStack_Size(stack) > 0)
{
LinkStack_Pop(stack);
}
}
/*
往栈中压入数据结点
如果成功,返回非0值,失败,返回0值
*/
int LinkStack_Push(LinkStack* stack, LinkStackNode* item)
{
int iret = 1;
TLinkStackNode *node = NULL;
node = (TLinkStackNode*)malloc(sizeof(TLinkStackNode));
iret = iret && (node != NULL) && (item != NULL);
if(iret)
{
node->item = item;
//压入到尾部
iret = List_Insert(stack,(LinklistNode*)node,List_Length(stack));
}
//如果插入失败,则释放node
if(!iret)
{
free(node);
}
return iret;
}
/*
从栈顶弹出数据结点,并从栈中移出该结点
如果成功,返回该结点指针,失败返回NULL
*/
LinkStackNode* LinkStack_Pop(LinkStack* stack)
{
LinkStackNode *ret = NULL;
TLinkStackNode *node = NULL;
int pos = List_Length(stack) - 1;
if(pos >= 0)
{
node = (TLinkStackNode*)List_Delete(stack,pos);
if(node != NULL)
{
ret = node->item;
free(node);
}
}
return ret;
}
/*
获取栈顶数据结点,不会移出栈顶结点
如果成功,返回该结点指针,失败返回NULL
*/
LinkStackNode* LinkStack_Top(LinkStack* stack)
{
LinkStackNode *ret = NULL;
TLinkStackNode *node = NULL;
int pos = List_Length(stack) - 1;
if(pos >= 0)
{
node = (TLinkStackNode*)List_Get(stack,pos);
if(node != NULL)
{
ret = node->item;
}
}
return ret;
}
/*
获取栈的当前元素个数
如果成功,返回元素个数,失败返回-1
*/
int LinkStack_Size(LinkStack* stack)
{
return List_Length(stack);
}
完整源码下载:
文件名:linkstack-1.0.tar.gz
链接: http://pan.baidu.com/s/1jG1mpca 密码: 5xrm
文件名:linkstack-1.1.tar.gz
链接: http://pan.baidu.com/s/1mgqtkbm 密码: q85e
说明:修复了由linklist.c中的List_Get()函数所引起的BUG,详情见链接!
编译步骤:
0.1 解压缩:tar -zxvf linkstack-1.1.tar.gz
0.2 进入目录:./configure
0.3 生成Seqlist:make
0.4 运行程序:./Linkstack