为了清楚的为读者展示每个功能模块如何实现,分得很细,以致有一些功能模块的运行结果要组合起来展示:比如说栈先初始化后才能插入元素(直接插也可以),但删除元素,和返回栈顶元素等需要先插入栈元素运行效果才能展现得更具体,当然,选择不同的功能选项,不插入栈元素也会有相应的输出;
作此说明是想告诉读者后面的运行结果展示可能会有点乱,当然每次结果输出上都会有文字标识
文末有完整代码
一、面板功能初始化
<1>.c文件对操作界面的初始化代码展示:
printf("选择你想实现的功能:\n");
printf("*-----------------------------------------------------------------------------------------*\n");
printf("**1:构造空栈 **\t\t"); printf("2:销毁栈 **\t"); printf("3:清空栈 **\t\n");
printf("**4:检测栈是否为空栈**\t\t"); printf("5:返回栈元素个数 **\t"); printf("6:返回栈顶元素 **\t\n");
printf("**7:插入栈顶元素 **\t\t"); printf("8:删除栈顶元素,并返回其值**\t"); printf("9:从底到顶依此访问栈元素**\t\n");
printf("**10:退出 ** **\n");
printf("*-----------------------------------------------------------------------------------------*\n");
<2>运行结果展示:
二、.c文件对变量的定义以及对函数的引用
int Choice = 0, Ele = 0;
SqStack s = { NULL };
while (1)
{
printf("输入功能序号:\n");
scanf_s("%d", &Choice);
if ((Choice > 10) || (Choice <= 0))
printf("输入非法,请重新选择!!\n");
switch (Choice)
{
case 1:
InitStack(&s);
break;
case 2:
DestroyStack(&s);
break;
case 3:
ClearStack(&s);
break;
case 4:
StackEmpty(&s);
break;
case 5:
StackLength(&s);
break;
case 6:
GetTop(&s);
break;
case 7:
Push(&s);
StackTraverse(&s);//遍历栈元素
break;
case 8:
Ele = Pop(&s);
printf("删除的栈顶元素为:%d\n", Ele);
break;
case 9:
StackTraverse(&s);
break;
case 10:
exit(0);
break;
}
三、.h文件对标准库的引用以及对顺序栈的表示
#pragma once
#include<stdio.h>
#include<stdlib.h>
#define Maxsize 25//顺序栈存储空间的初始分配量
typedef int SElemType;
//顺序栈的表示
typedef struct
{
SElemType* base;//栈底指针
SElemType* top;//栈顶指针
int stacksize;//栈可用的最大容量
}SqStack;
四、构造空栈InitStack函数的定义
<1>代码展示
//顺序栈的初始化
int InitStack(SqStack *S)
{
S->base = (SElemType*)malloc(sizeof(SElemType));//为顺序表分配一个最大容量为Maxsize的数组
if (!S->base)//存储分配失败
exit(0);
else
printf("成功初始化\n");
S->top = S->base;//top初始为base
S->stacksize = Maxsize;
return true;
}
<2>运行结果展示
前三次选择超范围,提示非法输入;第四次合法输入,成功初始化;
五、销毁栈DestroyStack函数的定义
<1>代码展示
//销毁栈
int DestroyStack(SqStack* S)
{
free(S->base);//释放栈底元素的空间
S->base = NULL;//并将栈底和栈顶的指针同时指向NULL
S->top = NULL;
S->stacksize = 0;//栈可用的最大容量赋值为0
if (S->base == NULL)
{
printf("栈销毁成功!\n");
return true;
}
else
{
printf("栈销毁失败!!\n");
return false;
}
}
<2>运行结果展示
第一次输入:1构造空栈 第二次输入:2销毁栈,成功销毁 第三、四次输入:7插入两个栈元素33 22 第五次输入:9从栈底到栈顶访问栈元素
六、 清空栈ClearStack函数的定义
<1>代码展示
//清空栈
int ClearStack(SqStack* S)
{
if (S->top == S->base)//两者地址相同
return true;
else
{
while (S->base < S->top)//因为顺序栈是地址连续的存储单元所以可以比较地址的大小
{
S->top--;//地址减减直到S->top的地址等于S->base的地址
}
if(S->top==S->base)
{
printf("成功清除\n");
return true;
}
else
{
printf("清除失败!!");
return false;
}
}
}
<2>运行结果展示
第一次输入:1构造栈 第二、三次输入:7插入栈元素33 22 第四次输入:3请空栈 第五次输入:4检测栈是否为空 因为清空了栈所以为空
七、检测StackEmpty函数的定义
<1>代码展示
//检测栈是否为空
int StackEmpty(SqStack* S)
{
if (S->top == S->base)
{
printf("空栈!!\n");
return false;
}
else
{
printf("非空栈!!\n");
return true;
}
}
<2>运行结果展示
第一次输入:构造空栈 第二次输入:检测栈是否为空 第三次:插入栈元素 第四次:检测栈元素是否为空
八、 检测StackLength函数的定义
<1>代码展示
//返回栈元素个数
int StackLength(SqStack* S)
{
printf("元素个数为:%d\n", S->top-S->base);//S->top在元素的上一个地址,S->top-S->base正好会等于栈元素个数
return true;
}
<2>运行结果
第一次输入:构造空栈 第二次输入:返回栈元素个数 第三四次:插入栈元素 第五次:返回元素个数
九、 检测GetTop函数的定义
<1>代码展示
//返回栈顶元素
int GetTop(SqStack *S)
{
if (S->top == S->base)
{
printf("为空栈,不存在元素\n");
return false;
}
else
{
printf("栈顶元素为:%d\n", *(S->top - 1));//通过指针读取地址的数据
return true;
}
}
<2>运行结果
第一次:构造链表 第二次:6返回栈顶元素 第三四次:7插入栈元素 第五次:6返回栈顶元素
十、 检测Push函数的定义
<1>代码展示
//插入栈顶元素
int Push(SqStack* S)
{
int Element=0;
if ((S->top - S->base) >= S->stacksize)//此时栈最大可用容量已满
{
S->base = (SElemType*)realloc(S->base, S->stacksize + 20 * sizeof(int));
if(S->base==NULL)
return false;
S->top = S->base + S->stacksize;
S->stacksize += 20 * sizeof(int);
}
printf("输入你想添加的元素:\n");
scanf_s("%d", &Element, sizeof(Element));
*S->top++ = Element;//等效于下面的语句
//*S->top=e;
//S->top++;
return true;
}
<2>运行结果展示
前面用到很多次,也为了避免篇幅过长,就不展示了
十一、 检测Pop函数的定义
<1>代码展示
//删除栈顶元素并返回值
int Pop(SqStack* S)
{
int e = 0;
if (S->top == S->base)
{
printf("空栈!!没有可以删除的元素\n");
}
else
{
e = *--S->top;
}
return e;
}
<2>输出结果展示
第一次:初始化 第二次:8删除空栈栈顶元素 第四五六:插入 33 22 61 第七次:8删除栈顶元素 第八次:9遍历栈元素
十二、 检测StackTraverse函数的定义
<1>代码展示
//从底到顶依此访问栈元素
int StackTraverse(SqStack* S)
{
int* p = S->base;//定义一个指针变量指向栈底
if (S->top == S->base)//如果栈底和栈顶存储地址相同即为空栈
{
printf("空栈!!\n");
return false;
}
else
{
printf("栈元素为:");
while (p <= S->top-1)//p地址从S->base一直向上移动直到移动到S->top-1
{//S->top总是指向栈顶元素的上一个
printf("%d\t", *p);//p为指针类型
p++;//地址上移
}
printf("\n");
return true;
}
}
<2>结果展示
第一次:构造空栈 第二次:遍历空栈 第三四次:7插入栈顶元素 第五次:遍历打印栈元素;
其实我们在每次插入完成的时候都使用了访问栈的StackTraverse函数
十二、完整代码展示
<1>.c
#include"Module.h"
int main()
{
printf("选择你想实现的功能:\n");
printf("*-----------------------------------------------------------------------------------------*\n");
printf("**1:构造空栈 **\t\t"); printf("2:销毁栈 **\t"); printf("3:清空栈 **\t\n");
printf("**4:检测栈是否为空栈**\t\t"); printf("5:返回栈元素个数 **\t"); printf("6:返回栈顶元素 **\t\n");
printf("**7:插入栈顶元素 **\t\t"); printf("8:删除栈顶元素,并返回其值**\t"); printf("9:从底到顶依此访问栈元素**\t\n");
printf("**10:退出 ** **\n");
printf("*-----------------------------------------------------------------------------------------*\n");
int Choice = 0, Ele = 0;
SqStack s = { NULL };
while (1)
{
printf("输入功能序号:\n");
scanf_s("%d", &Choice);
if ((Choice > 10) || (Choice <= 0))
printf("输入非法,请重新选择!!\n");
switch (Choice)
{
case 1:
InitStack(&s);
break;
case 2:
DestroyStack(&s);
break;
case 3:
ClearStack(&s);
break;
case 4:
StackEmpty(&s);
break;
case 5:
StackLength(&s);
break;
case 6:
GetTop(&s);
break;
case 7:
Push(&s);
StackTraverse(&s);//遍历栈元素
break;
case 8:
Ele = Pop(&s);
printf("删除的栈顶元素为:%d\n", Ele);
break;
case 9:
StackTraverse(&s);
break;
case 10:
exit(0);
break;
}
}
}
<2>.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#define Maxsize 25//顺序栈存储空间的初始分配量
typedef int SElemType;
//顺序栈的表示
typedef struct
{
SElemType* base;//栈底指针
SElemType* top;//栈顶指针
int stacksize;//栈可用的最大容量
}SqStack;
//顺序栈的初始化
int InitStack(SqStack *S)
{
S->base = (SElemType*)malloc(sizeof(SElemType));//为顺序表分配一个最大容量为Maxsize的数组
if (!S->base)//存储分配失败
exit(0);
else
printf("成功初始化\n");
S->top = S->base;//top初始为base
S->stacksize = Maxsize;
return true;
}
//销毁栈
int DestroyStack(SqStack* S)
{
free(S->base);//释放栈底元素的空间
S->base = NULL;//并将栈底和栈顶的指针同时指向NULL
S->top = NULL;
S->stacksize = 0;//栈可用的最大容量赋值为0
if (S->base == NULL)
{
printf("栈销毁成功!\n");
return true;
}
else
{
printf("栈销毁失败!!\n");
return false;
}
}
//清空栈
int ClearStack(SqStack* S)
{
if (S->top == S->base)//两者地址相同
return true;
else
{
while (S->base < S->top)//因为顺序栈是地址连续的存储单元所以可以比较地址的大小
{
S->top--;//地址减减直到S->top的地址等于S->base的地址
}
if(S->top==S->base)
{
printf("成功清除\n");
return true;
}
else
{
printf("清除失败!!");
return false;
}
}
}
//检测栈是否为空
int StackEmpty(SqStack* S)
{
if (S->top == S->base)
{
printf("空栈!!\n");
return false;
}
else
{
printf("非空栈!!\n");
return true;
}
}
//返回栈元素个数
int StackLength(SqStack* S)
{
printf("元素个数为:%d\n", S->top-S->base);//S->top在元素的上一个地址,S->top-S->base正好会等于栈元素个数
return true;
}
//返回栈顶元素
int GetTop(SqStack *S)
{
if (S->top == S->base)
{
printf("为空栈,不存在元素\n");
return false;
}
else
{
printf("栈顶元素为:%d\n", *(S->top - 1));//通过指针读取地址的数据
return true;
}
}
//插入栈顶元素
int Push(SqStack* S)
{
int Element=0;
if ((S->top - S->base) >= S->stacksize)//此时栈最大可用容量已满
{
S->base = (SElemType*)realloc(S->base, S->stacksize + 20 * sizeof(int));
if(S->base==NULL)
return false;
S->top = S->base + S->stacksize;
S->stacksize += 20 * sizeof(int);
}
printf("输入你想添加的元素:\n");
scanf_s("%d", &Element, sizeof(Element));
*S->top++ = Element;//等效于下面的语句
//*S->top=e;
//S->top++;
return true;
}
//删除栈顶元素并返回值
int Pop(SqStack* S)
{
int e = 0;
if (S->top == S->base)
{
printf("空栈!!没有可以删除的元素\n");
}
else
{
e = *--S->top;
}
return e;
}
//从底到顶依此访问栈元素
int StackTraverse(SqStack* S)
{
int* p = S->base;//定义一个指针变量指向栈底
if (S->top == S->base)//如果栈底和栈顶存储地址相同即为空栈
{
printf("空栈!!\n");
return false;
}
else
{
printf("栈元素为:");
while (p <= S->top-1)//p地址从S->base一直向上移动直到移动到S->top-1
{//S->top总是指向栈顶元素的上一个
printf("%d\t", *p);//p为指针类型
p++;//地址上移
}
printf("\n");
return true;
}
}
如果真有能看到最后的小伙伴,点个赞叭!!!