实现一个链接存储的栈

编程要求

实现 step2/LnkStack.cpp 中的LS_IsEmptyLS_LengthLS_PushLS_PopLS_Top五个操作函数,以实现判断栈是否为空、求栈的长度、进栈、出栈以及获取栈顶元素等功能。具体要求如下:

  • LS_IsEmpty:判断栈是否为空,若栈为空,则返回true,否则返回false

  • LS_Length:获取链式栈的长度;

  • LS_Push:将元素 x 进栈,若满栈则无法进栈,返回false,否则返回true

  • LS_Pop:若出栈成功(栈不为空),则返回true;否则(空栈),返回false

  • LS_Top:获取栈顶元素;

相关知识
链接存储的栈

栈的存储也可以采用链接存储的方式来实现。下面给出了一种基于链接存储的栈的实现方案:

如图 1 所示:该栈存储了 3 个元素 {56,77,15} ,其中 56 是栈顶元素。

这种实现方案中与栈相关的两个属性元素toplen介绍如下:

  • top: 指向栈顶结点的指针;
  • len: 栈中结点的个数。

特别说明:链接存储方式下,链表头结点作为栈顶结点,用指针top指向栈顶结点,栈结点个数由len给出。

基于toplen组织成的栈结构如下:

 
  1. struct LinkStack {
  2. LNode* top; // 栈顶指针
  3. int len; // 栈的长度
  4. };

为了讨论简单,我们假设栈元素的数据类型为整数:

 
  1. typedef int T; // 栈元素的数据类型

同时,每个结点的结构定义为:

 
  1. struct LNode {
  2. T data;
  3. LNode* next;
  4. };

据此,只要给定指向该结构的一指针ls,就可对栈进行出栈操作。

  • 进行出栈操作时,将指针top指向的当前栈顶元素 56 出栈,出栈后top指向下一个栈顶元素 77,这时的状态则如图 2 所示。

针对链式栈我们定义如下操作:

  • 创建栈:创建一个链式栈。具体操作函数定义如下: LinkStack* LS_Create()

  • 释放栈:释放栈所占用的空间。具体操作函数定义如下: void LS_Free(LinkStack* ls)

  • 清空一个栈:将链式栈变为空栈。具体操作函数定义如下: void LS_MakeEmpty(LinkStack* ls)

  • 判断栈是否为空:若栈为空,则返回true,否则返回false。具体操作函数定义如下: bool LS_IsEmpty(LinkStack* ls)

  • 求栈的长度:获取链式栈的长度。具体操作函数定义如下: int LS_Length(LinkStack* ls)

  • 将元素 x 进栈:将 x 进栈,若满栈则无法进栈,具体操作函数定义如下: void LS_Push(LinkStack* ls, T x)

  • 出栈:出栈的元素放入 item 。若出栈成功(栈不为空),则返回true;否则(空栈),返回false。具体操作函数定义如下: bool LS_Pop(LinkStack* ls, T& item)

  • 获取栈顶元素:获取栈顶元素放入 item 中。若获取失败(空栈),则返回false,否则返回true。具体操作函数定义如下: bool LS_Top(LinkStack* ls, T& item)

  • 打印栈中元素:从栈顶到栈底打印各结点数据元素。具体操作函数定义如下: void LS_Print(LinkStack* ls)

LnkStack.cpp

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

/* 创建栈 */
LinkStack* LS_Create()
{
    LinkStack* ls = (LinkStack*)malloc(sizeof(LinkStack));
    ls->top = NULL;  // 初始化栈顶指针为NULL
    ls->len = 0;     // 初始化栈的长度为0
    return ls;
}

/* 释放栈 */
void LS_Free(LinkStack* ls)
{
    LNode* curr = ls->top;
    while (curr) {
        LNode* next = curr->next;
        free(curr);
        curr = next;
    }
    free(ls);
}

/* 将栈变为空栈 */
void LS_MakeEmpty(LinkStack* ls)
{
    LNode* curr = ls->top;
    while (curr) {
        LNode* next = curr->next;
        free(curr);
        curr = next;
    }
    ls->top = NULL;  // 将栈顶指针置为NULL,表示栈为空
    ls->len = 0;     // 将栈的长度置为0
}

/* 判断栈是否为空 */
bool LS_IsEmpty(LinkStack* ls)
{
    // 判断栈是否为空,栈为空返回1,否则返回0
    if (ls->top == NULL)
        return 1;
    return 0;
}

/* 获取栈的长度 */
int LS_Length(LinkStack* ls)
{
    LNode* curr = ls->top;
    ls->len = 0;
    while (curr) {
        ls->len++;     // 遍历栈的每个结点,累加长度
        curr = curr->next;
    }
    return ls->len;
}

/* 将x进栈 */
void LS_Push(LinkStack* ls, T x)
{
    // 创建一个新的结点,并将数据x赋值给新结点的data域
    LNode* newNode = (LNode*)malloc(sizeof(LNode));
    newNode->data = x;
    newNode->next = ls->top;  // 新结点的next指向原来的栈顶
    ls->top = newNode;        // 更新栈顶指针为新结点
}

/* 出栈。出栈元素放入item;如果空栈,将返回false */
bool LS_Pop(LinkStack* ls, T& item)
{
    // 如果栈为空,无法进行出栈操作,返回false
    if (LS_IsEmpty(ls))
        return false;

    LNode* p = ls->top;  // 将栈顶结点指针保存到临时变量p
    item = p->data;      // 将栈顶结点的数据赋值给item
    ls->top = p->next;   // 更新栈顶指针为下一个结点
    free(p);             // 释放原来的栈顶结点的内存空间
    return true;
}

/* 读栈顶元素放入item。如果空栈,将返回false */
bool LS_Top(LinkStack* ls, T& item)
{
    // 如果栈为空,无法读取栈顶元素,返回false
    if (LS_IsEmpty(ls))
        return false;

    item = ls->top->data;  // 将栈顶结点的数据赋值给item
    return true;
}

/* 从栈顶到栈底打印各结点数据 */
void LS_Print(LinkStack* ls)
{
    if (ls->len == 0) {
        printf("The stack: Empty!\n");
        return;
    }
    printf("The stack (from top to bottom):");
    LNode* curr = ls->top;
    while (curr) {
        printf(" %d", curr->data);
        curr = curr->next;
    }
    printf("\n");
}

LnkStack.h

#if !defined(LINKED_STACK_H_985552)
#define LINKED_STACK_H_985552

typedef int T; // 数据元素类型

// 链表结点定义
struct LNode {
    T data;        // 数据域,存储元素值
    LNode* next;   // 指针域,指向下一个结点
};

// 链式栈定义
struct LinkStack {
    LNode* top;    // 栈顶指针,指向栈顶元素所在的结点
    int len;       // 栈的长度,记录栈中元素个数
};

// 创建栈
LinkStack* LS_Create();

// 释放栈
void LS_Free(LinkStack* ls);

// 将栈变为空栈
void LS_MakeEmpty(LinkStack* ls);

// 判断栈是否为空
bool LS_IsEmpty(LinkStack* ls);

// 获取栈的长度
int LS_Length(LinkStack* ls);

// 将元素x进栈
void LS_Push(LinkStack* ls, T x);

// 出栈,将出栈元素放入item中;如果栈为空,返回false
bool LS_Pop(LinkStack* ls, T& item);

// 读取栈顶元素,将栈顶元素放入item中;如果栈为空,返回false
bool LS_Top(LinkStack* ls, T& item);

// 从栈顶到栈底打印各结点数据
void LS_Print(LinkStack* ls);

#endif

Main.cpp

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "LnkStack.h"
#pragma warning(disable:4996)

int main()
{
    // 创建一个链式栈
    LinkStack* ls = LS_Create();

    // 定义存储用户输入的操作字符串
    char dowhat[100];

    while (true) {
        // 获取用户输入的操作字符串
        scanf("%s", dowhat);

        if (!strcmp(dowhat, "push")) {
            // 如果用户输入的操作是 "push"

            T x;
            scanf("%d", &x);
            // 读取用户输入的元素值 x

            LS_Push(ls, x);
            // 将元素 x 入栈
        }
        else if (!strcmp(dowhat, "pop")) {
            // 如果用户输入的操作是 "pop"

            T item;
            LS_Pop(ls, item);
            // 弹出栈顶元素,并将其存储在变量 item 中
        }
        else {
            // 如果用户输入的操作不是 "push" 也不是 "pop",则跳出循环
            break;
        }
    }

    int length = LS_Length(ls);
    // 获取栈的长度
    printf("Stack length: %d\n", length);

    LS_Print(ls);
    // 打印栈的元素

    LS_Free(ls);
    // 释放栈的内存

    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值