编程要求
实现 step2/LnkStack.cpp 中的LS_IsEmpty
、LS_Length
、LS_Push
、LS_Pop
和LS_Top
五个操作函数,以实现判断栈是否为空、求栈的长度、进栈、出栈以及获取栈顶元素等功能。具体要求如下:
-
LS_IsEmpty
:判断栈是否为空,若栈为空,则返回true
,否则返回false
; -
LS_Length
:获取链式栈的长度; -
LS_Push
:将元素 x 进栈,若满栈则无法进栈,返回false
,否则返回true
; -
LS_Pop
:若出栈成功(栈不为空),则返回true
;否则(空栈),返回false
; -
LS_Top
:获取栈顶元素;
相关知识
链接存储的栈
栈的存储也可以采用链接存储的方式来实现。下面给出了一种基于链接存储的栈的实现方案:
如图 1 所示:该栈存储了 3 个元素 {56,77,15} ,其中 56 是栈顶元素。
这种实现方案中与栈相关的两个属性元素top
和len
介绍如下:
top
: 指向栈顶结点的指针;len
: 栈中结点的个数。
特别说明:链接存储方式下,链表头结点作为栈顶结点,用指针
top
指向栈顶结点,栈结点个数由len
给出。
基于top
和len
组织成的栈结构如下:
struct LinkStack {
LNode* top; // 栈顶指针
int len; // 栈的长度
};
为了讨论简单,我们假设栈元素的数据类型为整数:
typedef int T; // 栈元素的数据类型
同时,每个结点的结构定义为:
struct LNode {
T data;
LNode* next;
};
据此,只要给定指向该结构的一指针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;
}