【六】栈的定义及实现

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值