1.特性
逻辑结构: 线性结构
存储结构:链式存储
顺序栈和链式栈的区别是:存储结构不同,实现的方式不同,顺序栈用顺序表实现而链式栈需要用链表实现。
操作:创建、入栈、出栈、判空、清空
2.结构体
// 入栈和出栈只在第一个节点位置操作
typedef int datatype;
typedef struct linkstack
{
datatype data; // 数据域
struct linkstack *next; // 指针域
} linkstack_t;
3.入栈
步骤:
(1)新建节点
(2)初始化新建节点,存入数据
(3)将新节点接入链表
(4)将栈针指向新节点
// 2.入栈 data是入栈的数据
// 参数上之所以采用二级指针,因为我们要随着入栈添加新的节点作为头,top需要永远指向当前链表的头,
// 那么修改main函数中的指针top,我们采用地址传递,需要传一级指针的地址,用二级指针来接收。
int PushLinkStack(linkstack_t **ptop, datatype data)
{
// 新建节点,保存数据。
linkstack_t *pnew = (linkstack_t *)malloc(sizeof(linkstack_t));
if (pnew == NULL)
{
perror("pnew malloc error");
return -1;
}
// 初始化节点,存入数据
pnew->data = data;
pnew->next = NULL;
// 将新节点连入链表
pnew->next = *ptop;
// 栈针移向新节点
*ptop = pnew;
return 0;
}
4.出栈
步骤:
(1)判断栈是否为空
(2)定义指针暂存要出栈的节点,也就是栈顶节点
(3)去除出栈节点中的数据
(4)移动栈针,第二个节点成为新的栈顶节点
(5)释放出栈的节点
// 3.判断栈是否为空
int IsEpLinkStack(linkstack_t *top)
{
return top == NULL;
}
// 4.出栈
datatype PopLinkStack(linkstack_t **ptop)
{
// 容错判断
if (IsEpLinkStack(*ptop))
{
perror("栈为空");
return 0;
}
// 定义pdel暂存出栈的节点
linkstack_t *pdel = *ptop;
// 取数
datatype res = (*ptop)->data;
// 移动栈针,第二个节点成为新的栈顶
*ptop = (*ptop)->next;
// 释放出栈的节点
free(pdel);
pdel = NULL;
printf("出栈元素为:%d\n", res);
return res;
}
5.清空栈
其实清空栈跟出栈差不多,只不过不需要输出数据,只需要把每个节点都释放了。
// 5.清空栈
void ClearLinkStack(linkstack_t **ptop) // 用二级指针,是因为清空后需要将main函数中的top变为NULL
{
while (!IsEpLinkStack(*ptop))
{
PopLinkStack(ptop);
// printf("%d", PopLinkStack(ptop));
}
printf("\n");
}
6.求栈的长度
求栈的长度,循环移动栈针,直到最后一个节点,计算中间有多少节点即可。
// 6.求栈的长度
int LengthLinkStack(linkstack_t *top) // 用一级指针,是因为我只是求长度,不需要修改main函数中top指针的指向
{
int length = 0;
while (top != NULL)
{
length++;
top = top->next;
}
printf("长度为%d\n", length);
return length;
}