数据结构——栈和队列

本文详细介绍了数据结构中的栈和队列,包括它们的顺序存储结构和链式存储结构,以及各自的基本操作。栈是后进先出的数据结构,适用于括号匹配、表达式求值等场景。队列遵循先进先出原则,常用于树的层次遍历、图的广度优先遍历等。同时,文中还探讨了栈和队列在实际问题中的应用,如迷宫求解和进制转换。
摘要由CSDN通过智能技术生成

栈和队列

文章目录



栈(Stack)

后进先出(LIFO)Last In First Out

栈的顺序存储结构(SqStack——Sequence Stack)

表示方法

#define MaxSize 10;
typedef struct SqStack {
   
    ElemType data[MaxSize];
    int top;				// 栈顶指针,指向栈顶数组的下标,而非位序
}SqStack;

SqStack S;

  • 栈顶指针:S.top,初始时 S.top = -1;

  • 栈顶元素:S.data[S.top];

  • 进栈操作(push):由于是顺序表,有最大存储空间限制,栈不满时,栈顶指针加 1,送值到栈顶元素。

  • 出栈操作(pop):出栈先判断是否空栈,非空,先取出栈顶元素,后栈顶指针减 1。

  • 栈空条件:S.top = -1;

  • 栈满条件:S.top = MaxSize - 1;

  • 栈的当前长度:S.top + 1;


基本操作

初始化 InitStack(SqStack &S)
InitStack(SqStack &S) {
   
    S.top = -1;				// 栈顶指针置为 -1,当第一个元素进栈,指针 + 1,便指向下标 0,即数组第一元素
}


判栈空 StackEmpty(SqStack S)
bool StackEmpty(SqStack S) {
   
    if (S.top == -1)
        return true;
    else
        return false;
}


进栈 Push(SqStack &S, ElemType x)
bool Push(SqStack &S, ElemType x) {
   
    if (S.top == MaxSize - 1)
        return false;			// 栈满
    S.top++;
    S.data[S.top] = x;			// 两步并一步:S.data[++S.top] = x;
    return true;
}


出栈 Pop(SqStack &S, ElemType &x)
bool Pop(SqStack &S, ElemType &x) {
   
    if (S.top == -1)
        return false;			// 栈空
    x = S.data[S.top--];		// 先返回,再减 1。【注】看变量和 ++ / -- 的位置,在前先执行。变量在前先返回。
    return true;
}


读栈顶元素 GetTop(SqStack &S, ElemType &x)
bool GetTop(SqStack &S, ElemType &x) {
   
    if (S.top = -1)
        return false;			// 栈空读取不到任何元素。
    x = S.data[S.top];
    return true;
}

读栈顶其实就是在判断栈是否为空罢了。


共享栈

栈 0 从前向后移动,栈 1 从后先前移动。

typedef struct SqStack {
   
    ElemType data[MaxSize];
    int top0;
    int top1;
}SqStack;
  • 栈顶指针:初始时,S.top0 = -1; S.top1 = MaxSize;

  • 栈顶元素:S.data[S.top0]; S.data[S.top1];

  • 进栈操作(push):

    • 栈 0:栈顶指针加 1,再存数。
    • 栈 1:栈顶指针减 1,再存数。
  • 出栈操作(pop):

    • 栈 0:取数,栈顶指针减 1
    • 栈 1:取数,栈顶指针加 1
  • 栈空:

    • 栈 0:S.top0 = -1;
    • 栈 1:S.top1 = MaxSize;
  • 栈满:S.top0 = S.top1 - 1;

  • 栈当前长度:

    • 栈 0:S.top0 + 1;
    • 栈 1:MaxSize - S.top1;



栈的链式存储结构(LiStack——LinkStack)

链式存储没有最大长度 MaxSize 的限制,不存在栈满上溢情况。

链式存储的栈使用单链表、双链表都可以实现,双链表实现非常简单,但是存储密度不高,一般使用单链表

栈的特点是后进先出,如果我们在单链表的尾部进栈,则栈顶指针指向尾部,进栈时,可以实现栈顶指针“先加 1”,再添加数据元素的操作;但是在出栈时,由于是单链表,数据元素取出后,栈顶指针无法“减 1”,因此在表尾进行操作并不合理。

所以基本操作都在表头实现,这时,回想前面单链表中的头插法,恰好满足了“后进先出”的特点。

表示方法

typedef struct Linknode {
   
    ElemType data;
    struct Linknode *next;
} *LiStack;

LiStack p 等价于 Linknode *p,前者强调栈,后者强调数据元素。

  • 栈顶指针:S 即单链表的第一个数据元素的地址,也就是栈顶地址,S 可看作栈顶指针。


基本操作

只需操作栈顶,因此使用不带头结点的单链表更加方便~

初始化:InitStack(LiStack &S)
void InitStack(LiStack S) {
   
    S = NULL;
}


判栈空:StackEmpty(LiStack S)
bool StackEmpty(LiStack S) {
   
    if (S == NULL)
        return true;
}


进栈:Push(LiStack &S, Linknode *p)
bool Push(LiStack S, Linknode *p) {
   
    if (p == NULL)
        retur
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值