嵌入式学习-线性表Day03-栈
栈
顺序栈
2)入栈
3)出栈
链式栈
栈
什么是栈?
只能在一端进行插入和删除操作的线性表(又称为堆栈),进行插入和删除操作的一端称为栈顶,另一端称为栈底
栈特点:
先进后出 FILO first in last out FILO
顺序栈
1)逻辑结构:线性结构
2)存储结构:顺序存储
3)操作:入栈、出栈
typedef struct seqstack
{
int * data;
int maxlen;
int top;
}seqstack_t;
1)创建一个空的栈
2)入栈
判满
移动栈针
将数据入栈
3)出栈
判空
移动栈针
将数据出栈
#ifndef _SEQSTACK_H_
#define _SEQSTACK_H_
typedef struct seqstack
{
int* data;//指向栈的存储位置
int maxlen;//保存栈的最大长度
int top;//称为栈针,用的时候,心里面可以将按照顺序表里的last来使用
//top 始终代表当前栈内最后一个有效元素的下标
}seqstack_t;
//1.创建一个空的栈
seqstack_t *CreateEpSeqStack(int len);//len代表的是创建栈的时候的最大长度
//2.判断是否为满,满返回1 未满返回0
int IsFullSeqStack(seqstack_t *p);
//3.入栈
int PushStack(seqstack_t *p, int data);//data代表入栈的数据
//4.判断栈是否为空
int IsEpSeqStack(seqstack_t *p);
//5.出栈
int PopSeqStack(seqstack_t *p);
//6. 清空栈
void ClearSeqStack(seqstack_t *p);
//7. 获取栈顶数据(注意不是出栈操作,如果出栈,相当于删除了栈顶数据,只是将栈顶的数据获取到,不需要移动栈针)
int GetTopSeqStack(seqstack_t *p);
//8. 求栈的长度
int LengthSeqStack(seqstack_t *p);
#endif
链式栈
逻辑结构:线性结构
存储结构:链式存储
操作:入栈出栈
#ifndef _LINKSTACK_H_
#define _LINKSTACK_H_
//入栈和出栈只在第一个节点位置操作
typedef int datatype;
typedef struct linkstack
{
datatype data;//数据域
struct linkstack *next;//指针域
}linkstack_t;
//1.创建一个空的栈
void CreateEpLinkStack(linkstack_t **ptop);
//2.入栈 data是入栈的数据
参数上之所以采用二级指针,因为我们要随着入栈添加新的节点作为头,top需要永远指向当前链表的头,
那么修改main函数中的top,我们采用地址传递
int PushLinkStack(linkstack_t **ptop, datatype data);
//3.判断栈是否为空
int IsEpLinkStack(linkstack_t *top);
//4.出栈
datatype PopLinkStack(linkstack_t **ptop);
//5.清空栈
void ClearLinkStack(linkstack_t **ptop);//用二级指针,是因为清空后需要将main函数中的top变为NULL
//6.求栈的长度
int LengthLinkStack(linkstack_t *top);//用一级指针,是因为我只是求长度,不需要修改main函数中top指针的指向
//7.获取栈顶数据,不是出栈,不需要移动main函数中的top,所以用一级指针
datatype GetTopLinkStack(linkstack_t *top);
#endif
linkstack.c
#include<stdio.h>
#include<stdlib.h>
//入栈和出栈只在第一个节点位置操作
typedef int datatype;
typedef struct linkstack
{
datatype data;//数据域
struct linkstack *next;//指针域
}linkstack_t;
//1.创建一个空的栈
void CreateEpLinkStack(linkstack_t **ptop)//*ptop == top
{
*ptop = NULL;
}
//2.入栈 data是入栈的数据
// 参数上之所以采用二级指针,因为我们要随着入栈添加新的节点作为头,top需要永远指向当前链表的头,
// 那么修改main函数中的top,我们采用地址传递
int PushLinkStack(linkstack_t **ptop, datatype data)
{
//1.开辟空间存数据并初始化
linkstack_t * pnew = (linkstack_t *)malloc(sizeof(linkstack_t));
if(pnew == NULL)
{
perror("PushLinkStack err");
return -1;
}
pnew->data = data;
pnew->next = NULL;
//2.将新节点插入无头单向链表中作为第一个节点
pnew->next = *ptop;
//3.移动栈针
*ptop = pnew;
return 0;
}
//3.判断栈是否为空
int IsEpLinkStack(linkstack_t *top)
{
return top == NULL;
}
//4.出栈
datatype PopLinkStack(linkstack_t **ptop)
{
//0.容错判断,判空
if(IsEpLinkStack(*ptop))
{
perror("PopLinkStack err");
return -1;
}
//1.定义pdel指向被删除节点
linkstack_t *pdel = *ptop;
//2.定义一个变量temp保存出栈数据
datatype temp = pdel->data;
//3.移动栈针
*ptop = pdel->next;
//4.释放被删除节点
free(pdel);
pdel =NULL;
//5.返回数据
return temp;
}
//5.清空栈
void ClearLinkStack(linkstack_t **ptop)//用二级指针,是因为清空后需要将main函数中的top变为NULL
{
//只要不为空就出栈
while (!IsEpLinkStack(*ptop))
PopLinkStack(ptop);
}
//6.求栈的长度
int LengthLinkStack(linkstack_t *top)//用一级指针,是因为我只是求长度,不需要修改main函数中top指针的指向
{
//遍历无头单向链表,求长度
int len = 0;
while (top != NULL)
{
len++;
top=top->next;
}
return len;
}
//7.获取栈顶数据,不是出栈,不需要移动main函数中的top,所以用一级指针
datatype GetTopLinkStack(linkstack_t *top)
{
// 只要不为空就返回数据
if(!IsEpLinkStack(top))
return top->data;
return -1;
}
int main(int argc, char const *argv[])
{
// linkstack_t *top = NULL;
linkstack_t *top;
CreateEpLinkStack(&top);
for(int i=1;i<=5;i++)
PushLinkStack(&top,i);
printf("top value is %d\n",GetTopLinkStack(top));//5
printf("len is %d \n",LengthLinkStack(top));//5
while (!IsEpLinkStack(top))
printf("%d ",PopLinkStack(&top));//5 4 3 2 1
printf("\n");
return 0;
}
总结:
顺序栈和链式栈的区别是什么?
1.存储结构不同,顺序栈相当于数组,连续的,链式栈 链表非连续的
2.顺序栈的长度受限制,而链栈不会