当前位置: 首页 > news >正文

栈与队列(C语言版)

文章目录

  • 栈与队列
    • 1. 栈
      • 基本操作
      • 实现(基于链表)
        • 代码
        • 运行结果
      • 应用场景
    • 2. 队列
      • 基本操作
      • 实现
        • 代码
        • 运行结果
      • 应用场景

栈与队列

1. 栈

栈是一种操作受限的线性结构。操作受限体现在,栈只能在一端添加和删除元素,符合后进先出 ( LIFO ) 的特性,如下图所示:

在这里插入图片描述

基本操作

  1. 入栈
  2. 出栈
  3. 查看栈顶元素
  4. 判空

实现(基于链表)

代码
// Stack.h
// 定义结点类型
typedef struct node {
    int val;
    struct node* next;
 } Node;
 
// API
void push_stack(Node** pstack, int val);
int  pop_stack(Node** pstack);
int  peek_stack(Node* stack);
bool is_empty(Node* stack);
// Stack.c
#include "stack.h"
#include <stdlib.h>
#include <stdio.h>

void push_stack(Node** pstack, int val) {
    // 头插法
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->val = val;
    newNode->next = NULL;

    newNode->next = *pstack;
    *pstack = newNode;
}

int pop_stack(Node** pstack) {
    if (*pstack == NULL) {
        printf("栈为空,无法弹出元素");
        return -1;
    }

    int pop_val = (*pstack)->val;
    *pstack = (*pstack)->next;

    printf("弹出元素:%d\n", pop_val);
    return pop_val;
}

int  peek_stack(Node* stack) {
    if (stack == NULL) {
        printf("栈为空, 无法查看栈顶元素\n");
        return -1;
    }

    printf("栈顶元素:%d\n", stack->val);

    return stack->val;
}

bool is_empty(Node* stack) {
    if (stack) {
        printf("栈不为空\n");
        return false;
    }
    printf("栈为空\n");
    return true;
}
// main.c
#include<stdio.h>
#include"stack.h"

int main(void) {
    Node* stack = NULL;
    push_stack(&stack, 1);
    push_stack(&stack, 2);

    peek_stack(stack);
    pop_stack(&stack);

    peek_stack(stack);
    is_empty(stack);
    pop_stack(&stack);

    peek_stack(stack);
    is_empty(stack);

    return 0;

}
运行结果

在这里插入图片描述

应用场景

栈的应用场景是多种多样的:

  • 函数调用栈
  • 符号匹配问题
  • 表达式求值
  • 深度优先搜索(DFS)
  • . . .

2. 队列

队列是另一种操作受限的线性结构。操作受限体现在,队列只能在一端添加元素,在另一端删除元素,符合**先进先出(FIFO)**的特性。

在这里插入图片描述

基本操作

  1. 入队列
  2. 出队列
  3. 查看队头元素
  4. 判空

实现

代码
  1. 用链表实现

  2. 用数组实现(没使用循环数组的方法, 没有自动扩容功能

    // Queue.h
    #define N 10
    
    typedef struct {
        int elements[N];
        int front;
        int rear;
        int size;
    } Queue;
    
    // API
    Queue* create_queue();
    void destroy_queue(Queue* q);
    
    void push_queue(Queue* q, int val);
    int pop_queue(Queue* q);
    int peek_queue(Queue* q);
    
    bool is_empty(Queue* q);
    bool is_full(Queue* q);
    
    // Queue.c
    #include "queue.h"
    #include <stdio.h>
    #include <malloc.h>
    
    Queue* create_queue() {
        Queue* que = (Queue*)malloc(sizeof(Queue));
        que->front = 0; // 队头
        que->rear = -1; // 队尾
        que->size = 0;
    
        return que;
    }
    
    void destroy_queue(Queue* q) {
        free(q);
        printf("队列已释放\n");
    }
    
    void push_queue(Queue* q, int val) {
        if (is_full(q)) {
            printf("队列已满,无法插入元素\n");
            return;
        }
    
        if (q->rear == N - 1) { // 队尾指针已经到数组尾部边界,需要将元素移动到数组头部
            for (int i = q->front, j = 0; i <= q->rear; i++, j++) {
                q->elements[j] = q->elements[i];
            }
            q->front = 0;
            q->rear = q->size - 1;
        }
    
        q->elements[q->rear + 1] = val;
        q->rear++;
        q->size++;
        printf("成功在队尾插入元素:%d\n", val);
    }
    
    int pop_queue(Queue* q) {
        if (is_empty(q)) {
            printf("队列为空,无法弹出元素\n");
            return -1;
        }
        int pop_val = q->elements[q->front];
        q->front++;
        q->size--;
        printf("成功在队头弹出元素:%d\n", pop_val);
    
        return pop_val;
    }
    
    int peek_queue(Queue* q) {
        if (is_empty(q)) {
            printf("队列为空,无法查看元素\n");
            return -1;
        }
    
        return q->elements[q->front];
    }
    
    bool is_full(Queue* q) {
        if (q->rear - q->front == N - 1) {
            // printf("队列已满\n");
            return true;
        }
    
        return false;
    }
    
    bool is_empty(Queue* q) {
        if (q->rear < q->front) {
            // printf("队列为空\n");
            return true;
        }
    
        return false;
    }
    
    // main.c
    #include <stdio.h>
    #include "queue.h"
    
    int main(void) {
        Queue* que = create_queue();
    
        pop_queue(que);
        
        push_queue(que, 1);
        push_queue(que, 2);
        push_queue(que, 3);
    
        printf("查看队头元素:%d\n", peek_queue(que));
        pop_queue(que);
        printf("查看队头元素:%d\n", peek_queue(que));
    
        push_queue(que, 4);
        push_queue(que, 5);
        push_queue(que, 6);
        push_queue(que, 7);
        push_queue(que, 8);
        push_queue(que, 9);
        push_queue(que, 10);
    
        printf("队头索引:%d  队尾索引:%d\n", que->front, que->rear);
        printf ("队列元素个数:%d\n", que->size);
    
        push_queue(que, 11);
    
        printf("队头索引:%d  队尾索引:%d\n", que->front, que->rear);
        printf ("队列元素个数:%d\n", que->size);
    
        push_queue(que, 12);
    
        destroy_queue(que);
    
        return 0;
    }
    
运行结果

在这里插入图片描述

应用场景

  • 缓冲
  • 广度优先搜索(BFS)
  • . . .

相关文章:

  • 数据分析简介及其常用指标与方法
  • 毕业设计—基于Spring Boot的社区居民健康管理平台的设计与实现
  • java接口
  • DeepSeek教unity------Dotween
  • 部署postgresql_exporter监控pgsql
  • mysql增加字段操作以及关键字报错
  • MATLAB中regexpi函数用法
  • 想要追踪一个在传送带上运动的东西,该怎么选择工业相机呢,需要考虑哪些因素
  • 国产Linux OS:网络性能调优关键内核参数
  • 【医学影像AI】50个眼科影像数据集(1)分类任务
  • 软件测试技术之跨平台的移动端UI自动化测试(上)
  • VSCode 中使用 Snippets 设置常用代码块
  • 数据结构:顺序表(Sequence List)及其实现
  • Natural Language Processing NLP
  • Ubuntu轻松部署ToolJet低代码开发平台结合内网穿透远程访问
  • Blackbox.AI:高效智能的生产力工具新选择
  • 实用且美观,一款简单且模块化的UI组件库!
  • 【Linux】【网络】Libevent 内部实现简略版
  • CentOS 7.8 安装MongoDB 7 副本集(Replica Set)
  • Datablau产品全面接入DeepSeek
  • 缅甸发生5.0级地震
  • 杨建全已任天津市委副秘书长、市委市政府信访办主任
  • 遭车祸罹难的村医遇“身份”难题:镇卫生院否认劳动关系,家属上诉后二审将开庭
  • 关税互降后的外贸企业:之前暂停的订单加紧发货,后续订单考验沟通谈判能力
  • 阿里上财年营收增6%,蒋凡:会积极投资,把更多淘宝用户转变成即时零售用户
  • “朱雀玄武敕令”改名“周乔治华盛顿”?警方称未通过审核