栈的定义和算法的实现

一、栈的定义

栈(stack) 是限定仅在表尾进行插入或删除操作的线性表。因此,对栈来说,表尾端有其特殊含义,称为栈顶(top) ,相应地,表头端称为栈底(bottom) 。不含元素的空表称为空栈。

假设栈 S = ( a 1 , a 2 , . . . , a n ) S=(a_1,a_2,...,a_n) S=(a1,a2,...,an) ,则称 a 1 a_1 a1 为栈底元素, a n a_n an 为栈顶元素。栈中元素按 a 1 , a 2 , . . . , a n a_1,a_2,...,a_n a1,a2,...,an 的次序进栈,退栈的第一个元素应为栈顶元素。换句话说,栈的修改是按后进先出的原则进行的。因此,栈又称为后进先出(last in first out) 的线性表(简称 LIFO 结构)

二、栈的表示和实现

和线性表类似,栈也有两种存储表示方法。

1、顺序栈

顺序栈 ,即栈的书序存储结构是利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针top指示栈顶元素在顺序栈中的位置。一个常用的方法是,先为栈分配一个基本容量,然后在应用过程中,当栈的空间不够使用时再逐段扩大。为此,可以设定两个常量:STACK_INIT_SIZE(存储空间初始分配量)STACKINCREMENT(存储空间分配增量),并以下述类型说明作为顺序栈的定义。

typedef struct
{
  SElemType *base;  // 在栈构造之前和销毁之后,base的值为NULL
  SElemType *top;  // 栈顶指针
  int stacksize;  // 栈的当前可使用的最大容量,以元素为单位。
} SqStack;

栈的初始化操作为:按设定的初始分配量进行第一次存储分配,1)base 可称为栈底指针,在顺序栈中,它始终指向栈底的位置,若base的值为NULL,则表明栈结构不存在。2)top 为栈顶指针,其初值指向栈底,即top=base 可作为栈空的标记,没当插入新的栈顶元素时,指针top增1,删除栈顶元素时,指针top减1。因此 ,非空栈中的栈顶指针始终在栈顶元素的下一个位置上。

基本操作的算法描述(部分):

(1)、构造一个空栈

InitStack(&S) 操作结果:构造一个空栈S。

Status Init(SqStack s)  // Status(void)
{
  s.base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));  // SElemType(int)
  if(!s.base) exit(OVERFLOW);  // 存储分配失败
  s.top = s.base;
  s.stacksize = STACK_INIT_SIZE;
}
(2)、插入一个元素

Push(&S, e) :插入一个元素e

初始条件:栈s已存在

操作结果:插入元素e为新的栈顶元素。

CSDN图标
Status push(SqStack &s, SElemType e)
{  // 插入元素e为新的栈顶元素
  if(s.top-s.base >= s.stacksize)  // 栈满,追加存储空间
  {
    s.base = (SElemType *)realloc(s.base, (s.stacksize + STACKINCREMENT)*sizeof(SElemType));
    if(!s.base) exit(OVERFLOW); // 存储分配失败
    s.top = s.base + s.stacksize;
    s.stacksize += STACKINCREMENT;
  }
  *s.top++ = e;
}
(3)、返回一个元素(出栈)并删除其值

pop(&s, &e) : 返回一个元素并删除其值。

初始条件:栈S已存在且非空。

操作结果:删除S的栈顶元素,并用e返回其值。

Status pop(SqStack &s, SElemType &e)
{  // 若栈不空,则删除s的栈顶元素,用e返回其值,并返回OK;
   // 否则返回ERROR
  if(s.top == s.base) return ERROR;
  e = *(--s.top);
  return OK;
}
(4)、得到top的元素,且不删除top对应的值

只是单纯的返回栈顶对应的元素,不删除对应栈顶的值。

Status GetTop(SqStack s, SElemType &e){
  // 若栈不空,则用e返回s的栈顶元素,并返回OK,否则返回ERROR
  if(s.top == s.base) return ERROR;
  e = *(s.top - 1);
  return OK;
}
(5)、打印函数

打印这个栈所有元素的操作

Status print(SqStack *s)
{
  int *temp;
  temp = s->top;
  while(temp != s->base)
  {
    temp--;
    printf("%d", *temp);
  }
}
2、栈的链式表达

栈的链式表示如下图所示。

栈的链式表达部分描述:

(1)、定义链栈结构体
typedef struct Stack_Node
{
  ElemType data ;
  struct Stack_Node *next ;
} Stack_Node ;
(2)、栈的初始化
Stack_Node * Init_Link_Stack(void)
{
  Stack_Node *top;
  top = (Stack_Node *)malloc(sizeof(Stack_Node));
  top->next = NULL;
  return(top);
}
(3)、进栈
Status push(Stack_Node *top, ElemType e)
{
  Stack_Node *p;
  p = (Stack_Node *)malloc(sizeof(Stack_Node));
  if(!p) return ERROR; // 申请新结点失败,返回错误标志
  p->data = e;
  p->next = top-next;
  top->next = p;
  return OK;
}
(4)、出栈
Status pop(Stack_Node *top, ElemType &e)  // 将栈顶元素出栈
{
  Stack_Node *p;
  ElemType e;
  if(top->next == NULL) return ERROR;  // 栈空,返回错误标志
  p = top->next;
  e= top->data;
  top->next = p->next;  // 修改栈顶指针
  free(p);
  return OK;
}
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
是一种具有特定操作限制的线性数据结构,它的特点是先进后出(Last In First Out,LIFO)。定义包括对其基本操作的定义,即入(push)和出(pop)。 顺序是一种使用数组实现,具有固定大小的存储空间。其抽象数据类型(ADT)的定义如下: 1. 初始化:初始化一个空的顺序。 2. 入:将元素压入顶。 3. 出:删除并返回元素。 4. 取元素:返回元素的值。 5. 判空:判断是否为空。 6. 判满:判断是否已满。 链是一种使用链表实现,其大小可以动态调整。其抽象数据类型(ADT)的定义如下: 1. 初始化:初始化一个空的链。 2. 入:将元素压入顶。 3. 出:删除并返回元素。 4. 取元素:返回元素的值。 5. 判空:判断是否为空。 顺序算法实现: 1. 初始化:创建一个指定大小的数组作为的存储空间,初始化顶指针为-1。 2. 入:将要入元素放入顶指针指向的位置,顶指针自增1。 3. 出:返回顶指针指向的元素,并将顶指针减1。 4. 取元素:返回顶指针指向的元素的值。 5. 判空:顶指针是否等于-1。 6. 判满:顶指针是否等于的大小减1。 链算法实现: 1. 初始化:创建一个空链表作为的存储空间。 2. 入:创建一个新的节点,将要入元素放入节点的数据域,将节点插入到链表的头部。 3. 出:删除链表的头节点,并返回其数据域的值。 4. 取元素:返回链表的头节点的数据域的值。 5. 判空:判断链表是否为空。 以上就是顺序和链的抽象数据类型定义和基本操作的算法实现

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值