栈的定义
只允许在一端进行插入、删除的线性表(线性表是什么?可跳转至线性表编写,里面有我写的线性表操作,说白了线性表示就是具有相同数据类型的n个元素组成的优先序列,无法随机存取)
关于栈,个人认为最形象的比喻是“烤肉串”,串的时候是从上到下一个一个串进去,吃的时候是从最上面开始吃,一嘴撸到底的当我没说。
入栈出栈简图
相关操作(核心定义:只能在栈顶操作)
初始化:构造一个空栈并为之分配内存空间
销毁:销毁并释放栈所占用的内存空间
进栈:若栈未满,则将元素塞入栈使之成为新的栈顶
出栈:若栈非空,则弹出栈顶元素
读栈顶元素:若栈非空,则返回栈顶元素(区别于出栈,读栈不影响原栈元素结构)
判空:判断栈是否为空,为空则返回true,否则为false
题外话
出栈方式个数:假设有n个不同元素进栈,出栈方式个数则有
顺序栈操作
#pragma once
#define MAXSIZE 100
#define FALSE 0
#define TURE 1
#include"head.h"
typedef int DataType;
typedef int Status;
typedef struct
{
int top;
int elem[MAXSIZE];
}*SqStack,Stack;
void Init(SqStack S)
{
if (S == NULL)
{
//printf("内存分配失败\n");
//exit(FALSE);
return;
}
S->top = (SqStack)malloc(sizeof(SqStack));
S->top = 0;//初始长度为0
}
void Push(SqStack S,int data)
{
S->elem[S->top] = data;//每次入栈top+1
++S->top;//先加再用
}
void Pop(SqStack S)
{
if (S->top == 0)
{
printf("栈空,无法出战\n");
exit(FALSE);
}
S->top--;
}
void Visit(SqStack S)
{
if (S == NULL)
{
//printf("栈空,无法出战\n");
return;
}
printf("为您遍历如下\n");
for (int i = 0; i < S->top; i++)
{
printf("%d\n", S->elem[i]);
}
printf("遍历完成\n");
}
void test()
{
SqStack S;
Init(&S);
Push(&S,3);
Visit(&S);
Pop(&S);
Visit(&S);
}
int main()
{
test();
return 0;
}
链栈操作
链栈建议不要设置头结点,直接让头指针指向第一个元素(不给头结点分配空间)
#include"head.h"
typedef int Elemtype;
typedef struct node {
Elemtype data;
struct node* next;
}*Lstack,Lsnode;
//头指针不指向头结点,也就不需要为头结点分配内存
Lstack Init()
{
Lsnode* S = NULL;// = (Lstack)malloc(sizeof(Lstack));
return S;
}
//区分带头,不带头(链栈建议不带)
Lstack Push(Lstack S)
{
int elem;
Lsnode* node;
printf("输入三个入栈元素\n");
for (int i = 0; i < 3; i++)
{
node = (Lsnode*)malloc(sizeof(Lsnode));
node->next = NULL;
scanf("%d",&elem);
node->data = elem;
node->next = S;
S = node;
printf("元素%d入栈成功\n", S->data);
}
return S;
}
Lstack Pop(Lstack S)
{
S = S->next;
printf("初战成功\n");
return S;
}
void Visit(Lstack S)
{
if (S == NULL)
{
printf("空栈\n");
return;
}
else
{
printf("遍历如下\n");
while (S)
{
printf("%d\n", S->data);
S = S->next;
}
printf("遍历成功\n");
}
}
int main()
{
Lstack S = Init();
S = Push(S);
Visit(S);
S = Pop(S);
Visit(S);
}