3.2.2【链式栈 无头单向链表】

1. 概念

链式栈LinkStack

  1. 逻辑结构:线性结构
  2. 存储结构:链式存储
  3. 栈的特点:后进先出,仅栈顶进出

1.1. 示意图:最好理解:就这么看

思路:

  • 只需要操作 栈针的结点 即可
  • 不必纠结 表头表尾
  • 一般不存在 栈满,除非内存满了
  • 空栈,即 栈针 === NULL

2. 接口实现

2.1. 定义 链栈(无头链表结点)结构体

2.2. 创建 空的链栈(栈针置空)

2.3. 判空 (栈针 是否 为空)

2.4. 入栈(栈针上移)

思路:

  • 栈针top 永远指向无头单向链表的 第一个结点,即栈顶。
    • 栈空,则指向NULL
  • 新结点,总链接到栈顶结点之上,成为新栈顶

2.5. 出栈(栈针下移)

2.6. 获取栈顶数据(不 释放 栈顶结点)

2.7. 栈长(无头链表长度:即数据结点个数)

2.8. 清空(不空就出栈)

3. 总体代码

#include <stdio.h>
#include <stdlib.h>
#define DEBUG(Str) printf("%s %s %s %d\n", Str, __func__, __FILE__, __LINE__)

// 定义 链栈(无头链表结点)结构体
typedef int LinkStackDataType;
typedef struct LinkListNode
{
    LinkStackDataType data;    //结点数据域
    struct LinkListNode *next; //结点指针域
} LS;

// 创建 空的链栈(栈针置空)
void LSInit(LS **Ptop)
{
    *Ptop = NULL;
}

// 判空 (栈针 是否 为空)
int LSEmpty(LS *top)
{
    // 空返回1,不空返回0
    return top == NULL ? 1 : 0;
}

// 入栈(栈针上移)
int LSPush(LS **Ptop, LinkStackDataType data)
{
    // 创建 新的结点
    LS *Pnew = (LS *)malloc(sizeof(LS));
    if (NULL == Pnew)
    {
        DEBUG("malloc new node err");
        return -1;
    }
    Pnew->data = data;
    Pnew->next = NULL; //先初始化为NULL

    // 新结点插入链栈作为 栈顶结点,指向旧的栈顶结点
    Pnew->next = *Ptop;

    // 栈针 重新指向 新栈顶 的结点
    *Ptop = Pnew;

    return 0;
}

// 出栈(栈针下移)
// 二级指针,因为要改变 实参指针的值
LinkStackDataType LSPop(LS **Ptop)
{
    // 先容错 判空
    if (LSEmpty(*Ptop))
    {
        DEBUG("empty can't not Pop");
        return (LinkStackDataType)(-1);
    }

    // 定义临时变量存储 被删除的 栈顶结点 的数据
    // -> 优先于 * ,所以加()
    LinkStackDataType temp = (*Ptop)->data;

    // 定义临时指针存储 被删除的 栈顶节点 的地址
    LS *PDel = *Ptop;

    // 栈针下移
    *Ptop = (*Ptop)->next;

    free(PDel);
    PDel = NULL;

    return temp;
}

// 获取栈顶数据(不 释放 栈顶结点)
LinkStackDataType LSGetTopData(LS *Ptop)
{
    return LSEmpty(Ptop) ? (LinkStackDataType)(-1) : Ptop->data;
}

// 栈长(无头链表长度:即数据结点个数)
int LSLength(LS *ptop)
{
    int len = 0;

    // 判断 该指针是否空,而非其指向的结构体的next是否为空
    while (ptop != NULL)
    {
        len++;
        ptop = ptop->next;
    }

    return len;
}

// 清空(不空就出栈)
void LSClear(LS **Ptop)
{
    while (LSEmpty(*Ptop) != 1)
        LSPop(Ptop);
}

int main(int argc, char *argv[])
{
    // 先创建 栈针
    LS *Ptop = NULL;

    // 初始化 链栈
    LSInit(&Ptop);

    // 判断 空吗,和长度
    if (!LSEmpty(Ptop))
        printf("LinkStack Not Empty,Len is %d\n", LSLength(Ptop));
    else
        printf("LinkStack Is Empty,Len is 0\n");

    // 入栈
    for (int i = 1; i <= 5; i++)
        LSPush(&Ptop, i * 11);

    // 判断 空吗,和长度
    if (!LSEmpty(Ptop))
        printf("LinkStack Not Empty,Len is %d\n", LSLength(Ptop));
    else
        printf("LinkStack Is Empty,Len is 0\n");

    // 获取栈顶元素
    printf("ptop data is:%d\n", LSGetTopData(Ptop));

    // 清空 链栈
    LSClear(&Ptop);

    // 判断 空吗,和长度
    if (!LSEmpty(Ptop))
        printf("LinkStack Not Empty,Len is %d\n", LSLength(Ptop));
    else
        printf("LinkStack Is Empty,Len is 0\n");
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值