链表掌握了,那链栈你拿捏了吗?【数据结构】

引言

上一篇我们已经学会了静态栈的基本操作<让你一次了解透彻栈-CSDN博客>相当于是顺序表的一种又一形式;那么栈有没有链表的又一形式呢?

接下来我们便学习链栈

链栈的定义

链栈是使用链表来实现的栈结构,每个节点包含数据元素和指向下一个节点的指针。链栈的优点是不会出现栈满的情况,可以动态调整大小,但相比顺序栈,链栈的操作会稍微复杂一些。

在操作角度上,链栈就是进行头插法创建的单链表,只不过不能在中间位置进行元素的增加和删除,只能在栈顶处进行操作。

 创建链栈就是在头结点后将新元素压入栈内,可以类别单链表进行学习。

栈的基本操作

 链栈的操作主要包括初始化栈、进栈、出栈、获取栈顶元素、判断栈空等。

//定义链栈节点结构体
typedef struct Stack {
    int data;
    struct Stack *next;
} *LinkStack;

1.初始化栈

链栈初始化即先构造一个空栈,将栈顶指针top所指的头结点的指针域置空。

//初始化栈
LinkStack InitLinkStack() {
    LinkStack L = (LinkStack) malloc(sizeof(LinkStack));
    if(L != NULL)       //申请空间成功
    L->next = NULL;
    return L;
}

2.判断栈空

如果栈顶指针指向NULL则返回True,否则返回false。

//判栈空
bool EmptyLinkStack(LinkStack L) {
    if (L->next == NULL)//检查栈顶指针的值
    {
        return true;//栈L为空,函数返回true
    } else {
        return false;
    }
}

3.入栈操作

将数据元素val插入链栈的栈顶,将头结点的指针域指向新插入的栈顶元素。

当输入的val为-1时则表示输入结束。

//入栈操作,头插法
void PushLinkStack(LinkStack top) {
    //定义输入的元素
    int val;
    while (true) {
        printf("请输入链表中的元素:");
        scanf("%d", &val);

        if (val == -1) {
            break;
        }

        LinkStack p = (LinkStack) malloc(sizeof(LinkStack));
        if (p == NULL) {
            printf("申请失败!\n");     //新结点申请失败的情况
            return;
        } else {
            p->data = val;              //设置新结点的数据域
            p->next = top->next;        //设置新结点的指针城
            top->next = p;              //设置头结点指针城指向新的栈顶元素
        }
    }
}

4.出栈操作

删除栈顶数据元素,通过X返回删除数据的值,然后top指针指向下一个数据元素。

//出栈操作
void PopLinkStack(LinkStack top, int *x) {
    LinkStack node = (LinkStack) malloc(sizeof(LinkStack));
    if (top->next == NULL) {
        return;
    } else {
        node = top->next;           //将原栈顶数据元素弹出并赋给node
        *x = node->data;            //将原栈顶数据元素的数据赋值给x
        top->next = node->next;     //top指向链栈中的下一个数据元素
        free(node);         //释放原栈顶数据元素所占的空间
        return;
    }
}

5.获取栈顶元素

读取栈顶元素,并且返回该值。

//获取栈顶元素
void GetTop(LinkStack L, int *elem) {
    if (L->next == NULL) {
        return;
    } else {
        *elem = L->next->data;    //获取此时栈顶元素的数据域
        return;
    }
}

6.遍历链栈并且求链栈长

//遍历栈且求栈长
void PrintLinkStack(LinkStack L) {
    LinkStack p = (LinkStack) malloc(sizeof(LinkStack));

    p = L->next;        //指向栈顶结点

    int count = 0;      //设置计数器,记录元素个数
    while (p != NULL) {
        printf("%d\n", p->data);
        p = p->next;
        count++;
    }
    printf("栈的长度为:%d\n", count);
}

完整代码:

#include "stdbool.h"
#include "stdio.h"
#include "stdlib.h"

typedef struct Stack {
    int data;
    struct Stack *next;
} *LinkStack;


//初始化栈
LinkStack InitLinkStack() {
    LinkStack L = (LinkStack) malloc(sizeof(LinkStack));
    if (L != NULL)       //申请空间成功
        L->next = NULL;
    return L;
}

//判栈空
bool EmptyLinkStack(LinkStack L) {
    if (L->next == NULL)//检查栈顶指针的值
    {
        return true;//栈L为空,函数返回true
    } else {
        return false;
    }
}


//入栈操作,头插法
void PushLinkStack(LinkStack top) {
    //定义输入的元素
    int val;
    while (true) {
        printf("请输入链表中的元素:");
        scanf("%d", &val);

        if (val == -1) {
            break;
        }

        LinkStack p = (LinkStack) malloc(sizeof(LinkStack));
        if (p == NULL) {
            printf("申请失败!\n");     //新结点申请失败的情况
            return;
        } else {
            p->data = val;              //设置新结点的数据域
            p->next = top->next;        //设置新结点的指针城
            top->next = p;              //设置头结点指针城指向新的栈顶元素
        }
    }
}

//出栈操作
void PopLinkStack(LinkStack top, int *x) {
    LinkStack node = (LinkStack) malloc(sizeof(LinkStack));
    if (top->next == NULL) {

        return;
    } else {
        node = top->next;           //将原栈顶数据元素弹出并赋给node
        *x = node->data;            //将原栈顶数据元素的数据赋值给x
        top->next = node->next;     //top指向链栈中的下一个数据元素
        free(node);         //释放原栈顶数据元素所占的空间
        return;
    }
}

//获取栈顶元素
void GetTop(LinkStack L, int *elem) {
    if (L->next == NULL) {
        return;
    } else {
        *elem = L->next->data;
        return;
    }
}

// 判断链栈是否为空
int isEmpty(LinkStack stack) {
    return stack->next == NULL;
}

//遍历栈且求栈长
void PrintLinkStack(LinkStack L) {
    LinkStack p = (LinkStack) malloc(sizeof(LinkStack));
    p = L->next;
    int count = 0;
    while (p != NULL) {
        printf("%d\n", p->data);
        p = p->next;
        count++;
    }
    printf("栈的长度为:%d\n", count);
}


int main() {
    LinkStack L;
    L = InitLinkStack();

    printf("当前栈为空?(True/False):%s\n", EmptyLinkStack(L) ? "true" : "false");

    PushLinkStack(L);

    PrintLinkStack(L);

    int *x;
    GetTop(L, &x);
    printf("栈顶元素为%d\n", x);

    PopLinkStack(L, &x);
    printf("元素%d出栈\n", x);

    GetTop(L, &x);
    printf("栈顶元素为%d\n", x);

    PopLinkStack(L, &x);
    printf("元素%d出栈\n", x);

    printf("当前栈为空?(True/False):%s\n", EmptyLinkStack(L) ? "true" : "false");

    PrintLinkStack(L);
    return 0;
}

实现图片:

 有了前面单链表的知识基础,相信现在链栈的学习一定非常简单!

如果有任何问题欢迎留言~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值