054. 使用链表实现栈

在C语言中,使用链表实现栈是一种常见的方法。栈是一种后进先出(LIFO)的数据结构,支持两种主要操作:入栈(push)出栈(pop)。使用链表实现栈可以动态地管理内存,避免固定大小数组的限制。

C语言实现链表栈

#include <stdio.h>
#include <stdlib.h>

// 定义链表节点结构
typedef struct Node {
    int data;             // 数据域
    struct Node* next;    // 指针域,指向下一个节点
} Node;

// 定义栈结构
typedef struct {
    Node* top;            // 栈顶指针
} Stack;

// 初始化栈
void initStack(Stack* stack) {
    stack->top = NULL;    // 栈顶指针初始化为空
}

// 判断栈是否为空
int isEmpty(Stack* stack) {
    return stack->top == NULL;
}

// 入栈操作
void push(Stack* stack, int value) {
    Node* newNode = (Node*)malloc(sizeof(Node)); // 创建新节点
    if (newNode == NULL) {
        printf("内存分配失败!\n");
        exit(1);
    }
    newNode->data = value;    // 设置节点数据
    newNode->next = stack->top; // 新节点指向当前栈顶
    stack->top = newNode;      // 更新栈顶指针
}

// 出栈操作
void pop(Stack* stack) {
    if (isEmpty(stack)) {
        printf("栈为空,无法出栈!\n");
        return;
    }
    Node* temp = stack->top;  // 保存当前栈顶节点
    stack->top = stack->top->next; // 更新栈顶指针
    free(temp);               // 释放原栈顶节点
}

// 查看栈顶元素
int peek(Stack* stack) {
    if (isEmpty(stack)) {
        printf("栈为空,无法查看栈顶元素!\n");
        return -1; // 返回一个错误标志
    }
    return stack->top->data; // 返回栈顶元素
}

// 打印栈内容
void printStack(Stack* stack) {
    Node* temp = stack->top;
    printf("栈内容(从栈顶到栈底):");
    while (temp != NULL) {
        printf("%d ", temp->data);
        temp = temp->next;
    }
    printf("\n");
}

// 清空栈
void clearStack(Stack* stack) {
    while (!isEmpty(stack)) {
        pop(stack);
    }
}

int main() {
    Stack stack;
    initStack(&stack); // 初始化栈

    push(&stack, 10);
    push(&stack, 20);
    push(&stack, 30);

    printf("栈顶元素:%d\n", peek(&stack)); // 查看栈顶元素
    printStack(&stack); // 打印栈内容

    pop(&stack); // 出栈
    printf("出栈后栈顶元素:%d\n", peek(&stack)); // 查看栈顶元素
    printStack(&stack); // 打印栈内容

    clearStack(&stack); // 清空栈
    printf("清空栈后是否为空:%s\n", isEmpty(&stack) ? "是" : "否");

    return 0;
}

代码说明

链表节点结构 Node:每个节点包含一个数据域 data 和一个指针域 next,指向下一个节点。

栈结构 Stack:栈结构包含一个指针 top,指向栈顶节点。

初始化栈 initStack:将栈顶指针初始化为空。

判断栈是否为空 isEmpty:如果栈顶指针为空,返回 1(真),否则返回 0(假)。

入栈操作 push:创建一个新节点,将新节点的 next 指向当前栈顶,然后更新栈顶指针。

出栈操作 pop

  • 如果栈为空,打印错误信息并返回。

  • 保存当前栈顶节点,更新栈顶指针,释放原栈顶节点。

查看栈顶元素 peek

  • 如果栈为空,打印错误信息并返回错误标志。

  • 返回栈顶节点的数据。

打印栈内容 printStack:遍历链表,从栈顶到栈底打印所有元素。

清空栈 clearStack:通过循环调用 pop 函数,直到栈为空。

示例运行

输入:

无输入

输出:

栈顶元素:30
栈内容(从栈顶到栈底):30 20 10 
出栈后栈顶元素:20
栈内容(从栈顶到栈底):20 10 
清空栈后是否为空:是

栈的特点

  1. 后进先出(LIFO):最后入栈的元素最先出栈。
  2. 动态内存管理:使用链表实现栈可以动态地分配和释放内存,避免固定大小数组的限制。
  3. 效率:入栈和出栈操作的时间复杂度为 O(1)。
  4. 适用性:栈适用于需要后进先出处理的场景,如函数调用、括号匹配、表达式求值等。

通过使用链表实现栈,可以灵活地管理栈中的元素,满足后进先出的特性。

视频讲解

BiliBili: 视睿网络-哔哩哔哩视频 (bilibili.com)