目录
【1】栈 Stack
1》栈的定义
栈:是只允许在一端进行插入或删除的线性表,首先栈是一种线性表,但限定这种线性表只能在某一端进行插入和删除操作。
栈顶:线性表允许进行插入删除的一端
栈底:固定的,不允许进行插入和删除的另一端
空栈:不含任何元素的空表
栈又称为后进先出(Last In First Out)的线性表,简称LIFO结构
2》顺序栈
特性
逻辑结构:线性结构
存储结构:顺序结构
操作:创空栈、入栈、出栈、判空和判满
创空:
入栈:
出栈:
代码展示:
#include <stdio.h>
#include <stdlib.h>
typedef int data_t;//重定义整型
typedef struct stack//重定义栈节点结构体类型
{
int maxlen;//栈的最大长度,表示数组元素个数
data_t *data;//用来指向存放数据的指针相当于数组
int top;//定义一个变量表示栈顶的下标
} stack_t;
/*创空栈*/
stack_t *Create(int len)//len表示创建栈时的最大元素长度
{
stack_t *s = (stack_t *)malloc(sizeof(stack_t));//开辟顺序栈结构体的堆区空间
if (NULL == s)//容错判断
{
perror("malloc lost\n");
return NULL;
}
s->data = (data_t *)malloc(sizeof(data_t) * len);//开辟一个堆区空间,让data指针指向该空间,用于存放数据,相当于数组
if (NULL == s->data)//容错判断
{
perror("malloc lost\n");
}
//初始化结构体
s->maxlen = len;//最大元素个数初始化为建栈的长度
s->top = -1;//初始化栈顶下标为-1
return s;//返回创建的栈的结构体指针
}
/*判满*/
int Full(stack_t *p)
{
return p->top + 1 == p->maxlen;//当栈顶元素的下标加一就是数据元素个数 等于最大元素个数时,栈满
}
/*入栈*/
void Push(stack_t *p, int data)//栈的地址和要入栈的数据
{
if (Full(p))//先判满,容错判断
{
perror("In error\n");
}
p->top++;//下标先加一,因为初始化时下标为-1,需要将下标加到0下标处,开始入栈,后面也是每进一个数据,栈顶下标都加一
p->data[p->top] = data;//往加一后的下标位置插入数据
}
/*判空*/
int Empty(stack_t *p)
{
return p->top == -1;//当栈顶下标的值为-1时说明栈内没有数据,和创空栈时一样
}
/*出栈*/
int Pop(stack_t *p,int top)
{
if (Empty(p))//判空,容错判断
{
perror("Out error\n");
}
for(int i = top;i >= 0;i--)//for循环,从栈顶开始向下循环,依次打印栈内数据
{
printf("%d ",p->data[i]);
}
printf("\n");
}
int main(int argc, char const *argv[])
{
stack_t *S = Create(5);//开辟空顺序栈
Push(S, 5);//调用入栈函数
Push(S, 4);
Push(S, 3);
Push(S, 2);
Push(S, 1);
printf("出栈: ");
Pop(S, S->top);//调用出栈函数, 出栈先进后出 1 2 3 4 5
return 0;
}
运行结果:
2》链式栈
逻辑结构:线性结构
存储结构:链式存储
顺序栈和链式栈的区别:存储结构不同,实现的方式也不同,顺序栈是用顺序表实现而链式栈是用链表实现。
栈的操作:创空栈、入栈、出栈、判空
入栈:
出栈:
代码展示:
#include <stdio.h>
#include <stdlib.h>
typedef int data_t;
typedef struct node
{
data_t data;
struct node *next;
} Node_t, *Node_p;
/*创建一个空栈*/
void Create(Node_p *p) // Node_p 相当于Node_t *,所以 Node_p *p 相当于定义一个二级指针,接受一级指针的地址 p = &top
{
*p = NULL; //*p = top = NULL;
}
/*入栈*/
void Push(Node_p *p, int data)
{
Node_p p_new = (Node_p)malloc(sizeof(Node_t)); // 开辟一个新的要入栈的节点
if (NULL == p_new)
{
perror("malloc lost\n");
}
p_new->data = data; // 新节点初始化
p_new->next = *p;//让新节点连接到top栈顶上
*p = p_new;//让top栈顶移动到新节点处,让新节点成为栈顶
}
/*判空*/
int Empty(Node_p p)
{
return p == NULL;//当栈顶为空的时候,就是创空栈的时候
}
/*出栈*/
void Pop(Node_p *p)
{
if (Empty(*p))//判空,容错判断
{
perror("Empty\n");
}
while (*p != NULL)//当栈顶不是空,就进入循环
{
printf("%d ", (*p)->data);//先出栈顶的元素
Node_p p_del = *p;//定义一个p_del指针指向栈顶
*p = (*p)->next;//让栈顶向下移动,指向下一个节点
free(p_del);//释放之前的栈顶节点
p_del = NULL;//将p_del指针置空
}
printf("\n");
}
/*栈的长度*/
int Length(Node_p p)
{
int len = 0;//定义一个变量保存栈的长度
while (p != NULL)//当栈顶元素不为空就进入循环
{
len++;//让栈的长度加一
p = p->next;//栈顶指针向下移动,指向下一个节点
}
return len;//返回栈的长度
}
int main(int argc, char const *argv[])
{
Node_p top;//定义一个栈结构体类型的指针
Create(&top); // top = NULL,创空栈,此时栈里只有一个控制真
for (int i = 0; i < 5; i++)//循环调用入栈函数
Push(&top, i);
printf("栈的长度:%d\n", Length(top));//打印栈的长度
printf("出栈: ");
Pop(&top);//调用出栈函数,先入后出
return 0;
}
运行结果:
4》顺序栈的链式栈的区别
1> 顺序栈是顺序存储,内存连续,用顺序表实现;链表是链式存储,内存不连续,用链表实现。
2> 顺序栈的长度固定,而链栈不会。
今天的分享就到这里结束啦,如果有哪里写的不好的地方,请指正。
如果觉得不错并且对你有帮助的话请给个三连支持一下吧!