栈_栈和队列考研笔记

栈——栈和队列考研笔记


代码基本来源:2020王道数据结构考研复习指导 (侵删)

1. 栈的定义

栈是只允许在一端进行插入或删除操作线性表

  • 特点:后进先出 Last In First Out(LIFO)

  • 逻辑结构:与普通线性表相同(元素之间一一对应

  • 数据的运算:与普通线性表插入、删除操作有区别

  • 重要术语:栈顶、栈底、空栈

    • 栈顶:允许插入和删除的一端
    • 栈底:不允许插入和删除的一端
    • 空栈:栈中没有任何元素

2. 栈的实现方法

2.1 顺序栈 SqStack(Sequence Stack)

  • 物理结构(存储方式):用顺序存储的方式实现的栈(静态数组)
    • 给各个数据元素分配连续的存储空间,大小为
      MaxSize*sizeof(ElemType)
  • 缺点:预先需要分配一大片的连续空间(静态数组)
2.1.1 顺序栈的定义
#define MaxSize 10//定义栈中元素的最大个数
typedef struct{
    
    
    ElemType data[MaxSize];//静态数组存放栈中元素
    int top;//栈顶指针(数组下标)
}SqStack;
2.1.2 顺序栈的初始化
void InitStack(SqStack &S){
    
    
    S.top = -1;//初始化栈顶指针
}
2.1.3 顺序栈的判空
bool StackEmpty(SqStack S){
    
    
	if (S.top == -1)//栈空
        return true;
    else 			//不空
        return false;
}
2.1.4 顺序栈的进栈操作Push

进栈,若栈S未满,则将x加入使之成为新栈顶

bool Push(SqStack &S,ElemType x){
    
    
	if (S.top == MaxSize - 1)
 		return false;//栈满,报错
    //栈S未满,可将新元素入栈  
    S.data[++S.top] = x;//指针先加一,然后新元素入栈
}
2.1.5 顺序栈的出栈操作Pop

出栈,若栈S非空,则弹出栈顶元素并用x返回(引用)

void Pop(SqStack &S,ElemType &x){
    
    
	if (S.top == - 1)
 		return false;//栈空,报错
    //栈S未空,可将元素出栈
    x = S.data[S.top--];//元素先出栈,然后指针减一
}
2.1.6 顺序栈的读栈顶元素操作(查找操作)
  • 读栈顶元素:若栈S非空,则用x 返回栈顶元素

  • 栈的使用场景中大多只访问栈顶元素

bool GetTop(S, &x){
    
    
	if (S.top == -1)//栈空,报错
        return false;
    //栈非空,读栈顶元素
    x = S.data[S.top];//x记录栈顶元素
    return true;
}
2.1.7 顺序栈的代码注意
  • top 指向插入位置 or 指向栈顶元素二者各种具体操作的具体实现不同
    • top 指向栈顶元素:初始化 top = -1
    • top 指向插入位置:初始化 top = 1

2.2 共享栈 ShStack(Shareing Stack)

  • 两个栈共享同一片空间
  • 优点:相比于顺序栈(一个栈一片空间),可以节省内存空间
  • 缺点:仍需要声明栈的时候分配一片连续的存储空间
2.2.1 共享栈的定义
  • top0和top1代表两个栈的栈顶指针
    • top0:由小变大(数组下标随着元素入栈逐渐增加)
    • top1:由大变小(数组下标随着元素入栈逐渐减少)
#define MaxSize 10//定义栈中元素的最大个数
typedef struct{
    
    
	ElemType data[MaxSize];//静态数组存放栈中元素
	int top0;//0号栈栈顶指针
	int top1;//1号栈栈顶指针
}ShStack;
2.2.2 共享栈的初始化
  • top0和top1代表两个栈的栈顶指针
    • top0 = -1:0号栈中没有元素
    • top1 = MaxSize:1号栈中没有元素
void InitStack(ShStack &s){
    
    
	S.top0 = -1;//初始化栈顶指针
	S.top1 = MaxSize;
}
2.2.2 共享栈的栈满条件
  • top0 + 1 == top1:两个栈顶指针紧挨着(碰头)

2.3 链栈 LiStack(Linklist Stack)

  • 用链式存储方式实现的栈:存储结构和单链表相同
  • 对单链表的插入和删除操作限制即可
  • 进栈/出栈都只能在栈顶一端进行链头作为栈顶
  • 以下实现方式的对象:不带头结点的链栈
2.3.1 链栈的定义
typedef struct LinkNode{
    
    
	ElemType data;//数据域
    struct LinkNode *next;//指针域
} *LiStack;//栈类型定义
2.3.2 链栈的初始化
bool InitLiStack(LiStack &S){
    
    
    S = NULL;//初始化栈顶指针
    return true;
}
2.3.3 链栈的判空
bool LiStackEmpty(LiStack S){
    
    
    if (S == NULL)//栈顶指针为空——>空栈
        return true;
    else 
        return false;
}    
2.3.4 链栈的进栈操作(链表的后插操作)
bool Push(LiStack &S, ElemType x){
    
    
    LinkNode * t = (*LinkNode)malloc(sizeof(LinkNode));//动态分配新的结点
    if (t == NULL)
        return false;//内存不足,分配失败
    t->data = x;//填充结点
    if (S == NULL){
    
    //栈空
        S = t;//栈顶指针指向t
        return true;
    }
    //栈不空
    t->next = S;//将原栈顶结点连到新结点之后
    S = t;//栈顶指针指向最新入栈的结点
    return true;
}
2.3.5 链栈的出栈操作
bool Pop(LiStack &S, ElemType &x){
    
    
    if (S == NULL)//栈空,报错
        return false;
    LinkNode * t = S;//记录当前的栈顶指针
    x = S->data;//栈顶结点出栈
    S = S->next;//栈顶指针指向下一个结点
    free(t);//释放原栈顶结点的内存
    return true;
}
2.3.6 链栈栈顶元素的获取
bool GetTop(S, &x){
    
    
	if (S == NULL)//栈空,报错
        return false;
    //栈非空,读栈顶元素
    x = S->data;//x记录栈顶元素
    return true;
}
2.3.7 链栈的代码实现注意事项
  • 不带头结点比带头结点的实现方式更方便(区别于普通链表)
  • 链栈的栈顶指针始终指向最新入栈的结点

猜你喜欢

转载自blog.csdn.net/jimmy33777/article/details/105741705