1. 概念
链式栈Link
Stack
- 逻辑结构:线性结构
- 存储结构:链式存储
- 栈的特点:后进先出,仅栈顶进出
1.1. 示意图:最好理解:就这么看
思路:
- 只需要操作 栈针的结点 即可
- 不必纠结 表头表尾
- 一般不存在 栈满,除非内存满了
- 空栈,即 栈针 === NULL
2. 接口实现
2.1. 定义 链栈(无头链表结点)结构体
2.2. 创建 空的链栈(栈针置空)
2.3. 判空 (栈针 是否 为空)
2.4. 入栈(栈针上移)
思路:
- 栈针top 永远指向无头单向链表的 第一个结点,即栈顶。
-
- 栈空,则指向NULL
- 新结点,总链接到栈顶结点之上,成为新栈顶
2.5. 出栈(栈针下移)
2.6. 获取栈顶数据(不 释放 栈顶结点)
2.7. 栈长(无头链表长度:即数据结点个数)
2.8. 清空(不空就出栈)
3. 总体代码
#include <stdio.h>
#include <stdlib.h>
#define DEBUG(Str) printf("%s %s %s %d\n", Str, __func__, __FILE__, __LINE__)
// 定义 链栈(无头链表结点)结构体
typedef int LinkStackDataType;
typedef struct LinkListNode
{
LinkStackDataType data; //结点数据域
struct LinkListNode *next; //结点指针域
} LS;
// 创建 空的链栈(栈针置空)
void LSInit(LS **Ptop)
{
*Ptop = NULL;
}
// 判空 (栈针 是否 为空)
int LSEmpty(LS *top)
{
// 空返回1,不空返回0
return top == NULL ? 1 : 0;
}
// 入栈(栈针上移)
int LSPush(LS **Ptop, LinkStackDataType data)
{
// 创建 新的结点
LS *Pnew = (LS *)malloc(sizeof(LS));
if (NULL == Pnew)
{
DEBUG("malloc new node err");
return -1;
}
Pnew->data = data;
Pnew->next = NULL; //先初始化为NULL
// 新结点插入链栈作为 栈顶结点,指向旧的栈顶结点
Pnew->next = *Ptop;
// 栈针 重新指向 新栈顶 的结点
*Ptop = Pnew;
return 0;
}
// 出栈(栈针下移)
// 二级指针,因为要改变 实参指针的值
LinkStackDataType LSPop(LS **Ptop)
{
// 先容错 判空
if (LSEmpty(*Ptop))
{
DEBUG("empty can't not Pop");
return (LinkStackDataType)(-1);
}
// 定义临时变量存储 被删除的 栈顶结点 的数据
// -> 优先于 * ,所以加()
LinkStackDataType temp = (*Ptop)->data;
// 定义临时指针存储 被删除的 栈顶节点 的地址
LS *PDel = *Ptop;
// 栈针下移
*Ptop = (*Ptop)->next;
free(PDel);
PDel = NULL;
return temp;
}
// 获取栈顶数据(不 释放 栈顶结点)
LinkStackDataType LSGetTopData(LS *Ptop)
{
return LSEmpty(Ptop) ? (LinkStackDataType)(-1) : Ptop->data;
}
// 栈长(无头链表长度:即数据结点个数)
int LSLength(LS *ptop)
{
int len = 0;
// 判断 该指针是否空,而非其指向的结构体的next是否为空
while (ptop != NULL)
{
len++;
ptop = ptop->next;
}
return len;
}
// 清空(不空就出栈)
void LSClear(LS **Ptop)
{
while (LSEmpty(*Ptop) != 1)
LSPop(Ptop);
}
int main(int argc, char *argv[])
{
// 先创建 栈针
LS *Ptop = NULL;
// 初始化 链栈
LSInit(&Ptop);
// 判断 空吗,和长度
if (!LSEmpty(Ptop))
printf("LinkStack Not Empty,Len is %d\n", LSLength(Ptop));
else
printf("LinkStack Is Empty,Len is 0\n");
// 入栈
for (int i = 1; i <= 5; i++)
LSPush(&Ptop, i * 11);
// 判断 空吗,和长度
if (!LSEmpty(Ptop))
printf("LinkStack Not Empty,Len is %d\n", LSLength(Ptop));
else
printf("LinkStack Is Empty,Len is 0\n");
// 获取栈顶元素
printf("ptop data is:%d\n", LSGetTopData(Ptop));
// 清空 链栈
LSClear(&Ptop);
// 判断 空吗,和长度
if (!LSEmpty(Ptop))
printf("LinkStack Not Empty,Len is %d\n", LSLength(Ptop));
else
printf("LinkStack Is Empty,Len is 0\n");
}