数据结构笔记chapter 03_1_栈

3.1.1 栈的基本概念

线性表:具有相同数据类型的 n 个数据元素的有限序列,其中 n 为表长

栈(Stack):只允许在一端进行插入或者删除操作的线性表

  1. 逻辑结构:与普通线性表相同
  2. 数据运算:插入、删除操作有区别
  • 栈顶:允许插入、删除的一端
  • 栈底:不允许插入、删除的一端
  • 空栈:
  • 特点:后进先出(LIFO)

回顾之——线性表基本操作

  • 初始化:分配内存空间
  • 销毁:释放内存空间
  • 插入
  • 删除
  • 按值查找
  • 按位查找
  • 其他操作:求表长、输出、判空

总览之——栈的基本操作

  • 创建:初始化、分配内存空间
  • 销毁:释放内存空间
  • 进栈(增):若栈 S 未满,则将 x 加入使之成为新栈顶
  • 出栈(删):若栈 S 非空,则弹出栈顶元素,并用 x 返回
  • 查:获得栈顶元素,但不删除
  • 其他操作:判断是否为空

注意:增删只能在栈顶操作

卡特兰数(Catalan)

问:n 个不同元素进栈,出栈元素不同排列的个数为\frac{1}{n+1}C_{2n}^{n}


3.1.2 顺序栈的实现

顺序栈:用顺序存储方式实现的栈

顺序存储:给各个数据元素分配连续的存储空间,大小为:Maxsize*sizeof(ElemType)

缺点:栈的大小不可变

基本操作:

1、顺序栈的定义

#define Maxsize 10
typedef struct{

  Elemtype data[Maxsize];  //静态数组存放栈中元素
  int top;                //栈顶指针,int形式

}SqStack;

2、初始化操作

//初始化栈

void InitStack(SqStack &S){   //注意是传址

  S.top=-1;                  //初始化栈顶指针

}


//判断栈空

bool StakEmpty(SqStack S){

  if(S.top==-1)   //栈空
    return true;
  else            //不空
    return false;
  
}

3、进栈操作

//新元素进栈

bool Push(SqStack &S,ElemType x){
    
    if(S.top==Maxsize-1)    //栈满,报错
      return false;
    S.top=S.top+1;         //指针+1
    S.data[S.top]=x;       //指针作为数组下标,让新元素进栈
    
    //上述两行等价于  S.data[++S.top]=x;
}

4、出栈操作

对x传址:&x

栈顶元素出栈,利用栈顶指针作为静态数组下标

注意:数据还残留在内存中,只是逻辑上被删除了

//出栈操作

bool Pop(SqStack &S,ElemType &x){
    
    if(S.top==-1)      //栈空,报错
      return false;
    x=S.data[S.top];
    S.top=S.top-1;
       //上述两行等价于  x=S.data[S.top--]
    return true;
}

5、读取栈顶元素

//读取栈顶元素

bool GetTop(SqStack S,ElemType &x){  //注意!不需要对S传址,x要&x
    
    if(S.top==-1)      //栈空,报错
      return false;
    x=S.data[S.top];
    return true;
}

另一种方式,栈顶指针初始指向0

  top指向下一个可以插入的位置

则进栈时

//上述两行等价于  S.data[S.top++]=x;

出栈时

 //上述两行等价于  x=S.data[--S.top]

栈满的条件

top==MaxSize

共享栈:两个栈共享同一片空间

#define MaxSize 10

typedef struct{
    
    ElemType data[MaxSize];
    int top0;                //0号栈顶指针
    int top1;               //1号栈顶指针
}



//初始化栈

void InitStack(ShStack &S){
    
    S.top0=-1;
    S.top1=MaxSize;
}

 共享栈栈满条件:top0+1==top1

小结:创、增、删、查  T(n)=O(1)


3.1.3 链栈的实现

链栈:用链式存储方式实现的栈

基本操作:创(初始化)、增(进栈)、删(出栈)、查(获取栈顶元素)、判空、判满

回忆:

1、头插法建立单链表(对应进栈)


//后插操作:在p节点之后插入元素e

bool InsertNextNode(LNode *p,ElemType e){
    
    if (p==NULL)
      return false;
    LNode *s=(LNode *)malloc(sizeof(LNode));  //分配内存给新结点s
    if (s==NULL)
      return false;  //内存分配失败
    s->data=e;       //用结点s保存数据e
    s->next=p->next;
    p->next=s;      //将结点s连到p之后,先连s尾,再连s头
}

2、单链表的删除(对应出栈)

链栈的定义


//链栈的定义

typedef struct Linknode{
    
    ElemType data;           //数据域
    struct Linenode *next;  //指针域

}*LiStack;      //栈类型定义

带头结点的初始化

不带头结点的初始化(推荐)

(代码待补)

进出栈只能在栈顶一端进行(链头作为栈顶)

Guess you like

Origin blog.csdn.net/qq_41994825/article/details/121280965