个人主页:李仙桎
🔥 个人专栏: 《数据结构与算法》
⛺️生活的理想,就是为了理想的生活!
1、栈的定义
栈(stack)是只允许一端进行插入和删除的线性表
栈进出栈的变化形式
栈的顺序存储结构的有关操作
对于栈来讲,线性表的操作特性它都具备,由于它的特殊性,特别是插入和删除操作,我们改名为push和pop
线性表是用数组来实现的,对于栈这一种只能一头插入的线性表来说,下表为0的一段作为栈底
栈的链式存储结构的有关操作
讲完了栈的顺序存储,我们接着来看栈的链式存储
当使用链表实现链式栈时,通常选择链表的头部作为栈顶,因为这种方法更高效、实现也更简单:
- 在链表头部插入或删除节点只需要O(1)的时间复杂度,因为这些操作不需要遍历整个链表。这对于栈操作(即push和pop操作)非常理想,因为它们也应该是O(1)的时间复杂度
- 链表有头指针,栈有顶部指针,可以做到合二为一
链表的创建
typedef int STDataType;
typedef struct StackNode {
STDataType data;
struct StackNode* next;
} StackNode;
typedef struct LinkedStack{
StackNode* top;
int size;
} LinkedStack;
初始化
初始化一个空栈,只需要将栈顶指针设置为NULL,栈的大小设置为0
void Initialize(LinkedStack* stack) {
stack->top = NULL;
stack->size = 0;
}
压栈和出栈
int Push(LinkedStack* stack, int x) {
StackNode* Node = (StackNode*)malloc(sizeof(StackNode));
if (newNode == NULL) {
printf("Memory allocation failed\n");
return -1; // 使用-1表示错误情况,实际使用中应考虑其他错误处理方式
}
newNode->data = x ;
newNode->next = stack->top; // 新节点的下一个节点就是当前的栈顶
stack->top = newNode; // 更新栈顶为新节点
stack->size++;
return 1;
}
int Pop(LinkedStack* stack) {
if (stack->top == NULL) { // 检查栈是否为空
printf("Stack is empty\n");
return -1; // 使用-1表示错误情况,实际使用中应考虑其他错误处理方式
}
StackNode* temp = stack->top; // 临时保存栈顶节点
int data = temp->data; // 获取栈顶数据
stack->top = temp->next; // 更新栈顶指针为下一个节点
free(temp); // 释放原栈顶节点的内存
stack->size--;
return data; // 返回栈顶数据
}
检查栈是否为空
检查链式栈是否为空也很简单,只需检查栈顶指针是否为NULL。
int IsEmpty(LinkedStack* stack) {
return stack->top == NULL;
}