【数据结构】【王道】【栈与队列】不带头结点链栈的实现及基本操作(可直接运行)

总目录


各部分的解释已经以注释形式写于代码中。

1.说明

链栈实际上与单链表极为相似,区别主要在于判断条件以及链栈的操作只能在表头进行,即就是将单链表的操作固定在了表头。此处实现的是不带头结点的链栈,与带头结点的主要差别在于带头结点的链栈栈顶指针指向以及条件判断方面。实际上,相比于单链表带头结点对于不带头结点的优势,链栈由于都是在表头进行操作,所以带头结点链表的统一操作的优势便难以表现出来了。综上,带头结点的链栈实现其实与带头结点单链表相差不大,此处便不进行实现了。

2.基本操作

2.1 结构体构造

// 不带头结点
typedef struct LinkNode {
    int data;   // 数据域
    struct LinkNode *next; // 指针域
} LSNode, *LinkStack;   // 栈类型定义

2.2 初始化

// 初始化
void InitStack(LinkStack &S) {
    // 此为不带头结点的栈,与单链表相似,初始将栈顶指针指向NULL即可
    S = NULL;
}

2.3 判空

// 判空
bool Empty(LinkStack S) {
    // 栈为空的条件即栈顶指针指向NULL
    if(S == NULL) {
        return true;
    }
    return false;
}

2.4 入栈

// 入栈操作
// 由于栈只能从一端操作,所以每次都应该是从栈顶入栈
bool Push(LinkStack &S, int e) {
    // 申请分配空间
    LSNode *s = (LSNode*)malloc(sizeof(LSNode));
    // 内存分配失败的情况
    if(s == NULL) {
        return false;
    }
    s->data = e;
    // 由于每次都是从栈顶指针处插入,所以无需特殊处理
    // 令s指向S之前指向的地址
    s->next = S;
    // 使头指针指向s
    S = s;
    return true;
}

2.5 出栈

// 出栈操作
// 类似于单链表的删除操作,不过只能在栈顶进行出栈
bool Pop(LinkStack &S, int &e) {
    // 如果是空栈,则不可进行出栈操作
    if(S == NULL) {
        return false;
    }
    // 出栈结点即为栈顶指针指向的结点
    // 将出栈结点值赋给e
    e = S->data;
    // 临时结点,用于之后释放空间
    LSNode* p = S;
    // 使头指针指向下一个结点
    S = S->next;
    // 释放空间
    free(p);
    return true;
}

2.6 获取栈顶元素

// 获取栈顶元素
bool GetTop(LinkStack S, int &e) {
    // 栈为空的情况
    if(S == NULL) {
        return false;
    }
    e = S->data;
    return true;
}

2.7 输出栈中所有元素

// 输出栈中所有元素
// 由于栈只能从一端进行操作,所以想要输出所有元素,就必须要将所有元素弹出并输出
void PrintStack(LinkStack S) {
    if(Empty(S)) {
        printf("the stack is empty!");
    }
    while(!Empty(S)) {
        int x;
        Pop(S, x);
        printf("pop:%d\n", x);
    }
}

3.完整代码

#include<stdio.h>
#include<stdlib.h>

// 不带头结点
typedef struct LinkNode {
    int data;   // 数据域
    struct LinkNode *next; // 指针域
} LSNode, *LinkStack;   // 栈类型定义

// 初始化
void InitStack(LinkStack &S) {
    // 此为不带头结点的栈,与单链表相似,初始将栈顶指针指向NULL即可
    S = NULL;
}

// 判空
bool Empty(LinkStack S) {
    // 栈为空的条件即栈顶指针指向NULL
    if(S == NULL) {
        return true;
    }
    return false;
}

// 入栈操作
// 由于栈只能从一端操作,所以每次都应该是从栈顶入栈
bool Push(LinkStack &S, int e) {
    // 申请分配空间
    LSNode *s = (LSNode*)malloc(sizeof(LSNode));
    // 内存分配失败的情况
    if(s == NULL) {
        return false;
    }
    s->data = e;
    // 由于每次都是从栈顶指针处插入,所以无需特殊处理
    // 令s指向S之前指向的地址
    s->next = S;
    // 使头指针指向s
    S = s;
    return true;
}

// 出栈操作
// 类似于单链表的删除操作,不过只能在栈顶进行出栈
bool Pop(LinkStack &S, int &e) {
    // 如果是空栈,则不可进行出栈操作
    if(S == NULL) {
        return false;
    }
    // 出栈结点即为栈顶指针指向的结点
    // 将出栈结点值赋给e
    e = S->data;
    // 临时结点,用于之后释放空间
    LSNode* p = S;
    // 使头指针指向下一个结点
    S = S->next;
    // 释放空间
    free(p);
    return true;
}

// 获取栈顶元素
bool GetTop(LinkStack S, int &e) {
    // 栈为空的情况
    if(S == NULL) {
        return false;
    }
    e = S->data;
    return true;
}

// 输出栈中所有元素
// 由于栈只能从一端进行操作,所以想要输出所有元素,就必须要将所有元素弹出并输出
void PrintStack(LinkStack S) {
    if(Empty(S)) {
        printf("the stack is empty!");
    }
    while(!Empty(S)) {
        int x;
        Pop(S, x);
        printf("pop:%d\n", x);
    }
}

int main() {
    LinkStack S;
    InitStack(S);
    int x;
    Push(S, 3);
    GetTop(S, x);
    printf("push:%d\n", x);
    Push(S, 5);
    GetTop(S, x);
    printf("push:%d\n", x);
    Push(S, 7);
    GetTop(S, x);
    printf("push:%d\n", x);
    PrintStack(S);
}

4.运行结果

在这里插入图片描述

  • 5
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Silver Star

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值