栈的基础知识

一、栈的定义与特点

   栈:只能在表的一端(栈顶)进行插入和删除运算的线性表

  逻辑结构           与线性表相同,仍为一对一关系
  存储结构           用顺序栈和链栈存储均可,但顺序栈更常见
  访问结点时依照后进先出(LIFO)先进后出(FILO)的原则

   进栈------压入-----push()                        出栈-----弹出-----pop()

栈与线性表-仅在于运算规则不同

   线性表:
          逻辑结构:一对一
          存储结构:顺序表、链表
          运算规则:
                     顺序表——随机存取
                     链表——顺序存取

  栈
          逻辑结构:一对一
          存储结构:顺序栈、链栈
          运算规则:后进先出,先进后出

栈顶:线性表允许进行插入删除的那一端。

栈底:固定的,不允许进行插入和删除的另一端。

空栈:不含任何元素的空表。

栈的数学性质:n个不同元素进栈,出栈元素不同排列的个数为1/(n+1)C ~2n~ *n

栈的抽象数据类型:
    ADT Stack {
             数据对象:D={ai| ai∈ElemSet, i=1,2,...,n, n≥0 }
             数据关系:R1={ | ,ai-1,ai∈D, i=2,...,n } 约定an端为栈顶,a1端为栈底。
             基本操作:
                InitStack(&S) 操作结果:构造一个空栈 S。
                DestroyStack(&S) 初始条件:栈 S 已存在。 操作结果:栈 S 被销毁。
                ClearStack(&S) 初始条件:栈 S 已存在。 操作结果:将 S 清为空栈。
                StackEmpty(S) 初始条件:栈 S 已存在。 操作结果:若栈 S 为空栈,则返回TRUE,否则返回FALSE。
                StackLength(S) 初始条件:栈 S 已存在。 操作结果:返回栈 S 中元素个数,即栈的长度。
                GetTop(S, &e) 初始条件:栈 S 已存在且非空。 操作结果:用 e 返回S的栈顶元素。
                Push(&S, e) 初始条件:栈 S 已存在。 操作结果:插入元素 e 为新的栈顶元素。
                Pop(&S, &e) 初始条件:栈 S 已存在且非空。 操作结果:删除 S 的栈顶元素,并用 e 返
回其值。
} ADT Stack 

二、栈的顺序存储结构

顺序栈的存储方式
     同一般线性表的顺序存储结构完全相同,利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素。栈底一般在低地址端。
    附设top指针,指示栈顶元素在顺序栈中的位置。
    另设base指针,指示栈底元素在顺序栈中的位置。
为了方便操作,通常top指示真正的栈顶元素之上的下标地址
另外,用stacksize表示栈可使用的最大容量。

顺序栈的表示

#define MAXSIZE 100
       typedef struct{
          SElemType *base;
          SElemType *top;
          int stacksize;
        }SqStack;

顺序栈初始化(构造一个空栈)
(1)分配空间并检查空间是否分配失败,若失败则返回错误
(2)设置栈底和栈顶指针S.top = S.base;
(3)设置栈大小

Status InitStack( SqStack &S ){
             S.base =new SElemType[MAXSIZE];
             if( !S.base ) return OVERFLOW;
             S.top = S.base;
             S.stacksize = MAXSIZE;
              return OK;
 }

判断顺序栈是否为空
   bool StackEmpty( SqStack S ){
            if(S.top == S.base) return true;
            else return false;
  }

求顺序栈的长度
 int StackLength( SqStack S ){
           return S.top – S.base;
 }

清空顺序栈
Status ClearStack( SqStack S ){
             if( S.base )
             S.top = S.base;
             return OK;
}

销毁顺序栈
Status DestroyStack( SqStack &S ){
        if( S.base ){
            delete S.base ;
            S.stacksize = 0;
            S.base = S.top = NULL;
        }
        return OK;
}

 顺序栈进栈
       (1)判断是否栈满,若满则出错
       (2)元素e压入栈顶
       (3)栈顶指针加1
Status Push( SqStack &S, SElemType e){
            if( S.top - S.base== S.stacksize ) // 栈满
            return ERROR;
            *S.top++=e;
            return OK;
}

顺序栈出栈
        (1)判断是否栈空,若空则出错
        (2)栈顶指针减1
        (3)获取栈顶元素e
Status Pop( SqStack &S, SElemType &e){
          if( S.top == S.base ) // 栈空
          return ERROR;
          e= *--S.top;
          return OK;
}

取顺序栈栈顶元素
判断是否空栈,若空则返回错误
否则通过栈顶指针获取栈顶元素

Status GetTop( SqStack S, SElemType &e){
             if( S.top == S.base ) return ERROR; // 栈空
             e = *( S.top – 1 );
             return OK;
}

三、共享栈

     将编号为0和1的两个栈存放于一个数组空间V[m]中,栈底分别处于数组的两端。当第0号栈的栈
顶指针top[0]等于-1时该栈为空,当第1号栈的栈顶指针top[1]等于m时该栈为空。两个栈均从两端向中间增长。

 栈空:top[i] == bot[i] i表示栈的编号
 栈满:top[0]+1==top[1] 或top[1]-1==top[0]

共享栈定义
     #define Maxsize 100
     typedef struct{
           int top[2], bot[2];                            //栈顶和栈底指针
           SElemType data[Maxsize];           //栈数组
     }DblStack;

四、链栈


  采用链式结构存储的栈称为链栈,是运算受限的单链表,只能在链表头部进行操作,故没有必要附加头结点。栈顶指针就是链表的头指针。

  typedef struct StackNode {
           SElemType data;
           struct StackNode *next;
} StackNode, *LinkStack;

链栈初始化
void InitStack(LinkStack &S ){
     //构造一个空栈,栈顶指针置为空
     S=NULL;
}

链栈判空
Status StackEmpty(LinkStack S){
              if (S==NULL) return TRUE;
              else return FALSE;
}

链栈进栈
Status Push(LinkStack &S , SElemType e){
             p=new StackNode; //生成新结点p
             if (!p) exit(OVERFLOW);
             p->data=e;
             p->next=S; //??为什么这里不是S->next呢?
             S=p;
             return OK;
}

链栈出栈
Status Pop (LinkStack &S,SElemType &e){
            if (S==NULL) return ERROR;
            e = S-> data;
            p = S;
            S = S-> next;
            delete p;
            return OK;
}

取栈顶元素
SElemType GetTop(LinkStack S){
          if (S==NULL) exit(1);
          else
          return S–>data;
}

链栈的特点:

(1)不存在栈满(上溢)的情况。

(2)栈顶指针就是链表头指针。
(3)头插法建立单链表相当于进栈。
(4)单链表的删除相当于出栈。
 

你可能感兴趣的:(数据结构)