队列是一种重要的先进先出数据结构,在操作系统、算法、网络通信等领域广泛应用。本文将详细介绍如何使用C语言的数组实现队列,包括完整的代码实现、详细的图文解释和实用的测试用例!

        队列是一种线性数据结构,遵循先进先出原则:

  • 入队(Enqueue):元素从队尾加入;
  • 出队(Dequeue):元素从队首移除。

一、数据结构定义

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

#define MaxSize 5

int queue[MaxSize];
int front = -1;  // 队首指针,指向队首元素的前一个位置
int rear = -1;   // 队尾指针,指向队尾元素的位置

1. 初始空队列

2. 指针移动规则

        front:总是指向"队首元素的前一个位置";

        rear:总是指向"队尾元素的位置"。

二、关键操作详解

2.1 初始化队列(init_queue)

        首先将frontrear指针重置为-1,这是队列的空状态标志。

void init_queue() {
    front = -1;
    rear = -1;
    printf("队列初始化完成\n");
}

2.2 入队操作(add_queue

        入队操作的核心是检查队列是否已满,然后将新元素添加到队尾。满队判断条件rear >= MaxSize - 1于数组下标从0开始的特性。当rear指针移动到数组最后一个有效位置(对于MaxSize=5的情况,就是下标4)时,队列达到容量上限。

        操作顺序上,先移动rear指针再存入数据 —> 确保指针始终指向最后一个有效元素。

void add_queue(int value) {
    if (rear >= MaxSize - 1) {
        printf("队列已满,不能入队\n");
    } else {
        rear = rear + 1;          // 队尾指针后移
        queue[rear] = value;      // 存入新元素
        printf("入队成功:%d\n", value);
    }
}

2.3 出队操作(del_queue

        出队操作首先检查队列是否为空,判断条件front == rear简洁有效。当队列不为空时,操作流程是:

        先向前移动front指针,然后取出该位置的元素值。

        返回值考虑了错误情况,当队列为空时返回-1,我们可以通过检查返回值来判断操作是否成功。

int del_queue() {
    int tempvalue;
    
    if (front == rear) {
        printf("队列为空,不能出队\n");
        tempvalue = -1;
    } else {
        front = front + 1;          // 队首指针后移
        tempvalue = queue[front];   // 取出队首元素
        printf("出队成功:%d\n", tempvalue);
    }
    return tempvalue;
}

2.4 获取队首元素(get_front)

        返回:队首元素值,如果队列为空返回-1。

int get_front() {
    if (front == rear) {
        printf("队列为空\n");
        return -1;
    }
    return queue[front + 1];  // front指向前一个位置
}

2.5 获取队尾元素(get_rear)

        返回:队尾元素值,如果队列为空返回-1。

int get_rear() {
    if (front == rear) {
        printf("队列为空\n");
        return -1;
    }
    return queue[rear];  // rear指向最后一个元素
}

2.6 打印元素(print_queue)

        打印函数它只显示队列中的有效元素,循环从front+1开始到rear结束,遍历所有有效元素。当队列为空时,函数会给出提示信息。

void print_queue() {
    if (front == rear) {
        printf("队列为空\n");
        return;
    }
    
    printf("队列元素:");
    for (int i = front + 1; i <= rear; i++) {
        printf("%d ", queue[i]);
    }
    printf("\n");
}

2.7 主函数main

        首先初始化队列,建立初始状态;接着进行三次入队操作,展示队列逐渐填充的过程;然后进行一次出队操作,演示FIFO(先进先出)特性;最后进行满队测试,验证边界条件的处理。这种循序渐进的测试方法不仅验证了代码的正确性,也很好地展示了队列数据结构的工作原理。

int main() {
    printf("1. 初始化队列\n");
    init_queue();  // 状态:front=-1, rear=-1, 数组全0
    
    printf("\n2. 入队测试\n");
    add_queue(10);  
    add_queue(20);  
    add_queue(30);      
    print_queue();  // 显示:10 20 30
    
    printf("\n3. 出队测试\n");
    del_queue();    
    print_queue();  // 显示:20 30
    
    printf("\n4. 满队测试\n");
    add_queue(40); 
    add_queue(50);  
    add_queue(60);  // rear=5>MaxSize-1,提示已满
    print_queue();  // 显示:20 30 40 50
    
    return 0;
}

三、运行结果

        这个队列实现的主要优点是逻辑简单清晰代码易于理解。但也存在一些局限性:最大的问题是"假溢出"现象,即队列前面有空位但无法再利用,因为rear指针到达数组末尾后就无法继续入队。此外,固定大小的数组限制了队列的灵活性,无法动态调整容量。在实际应用中,通常采用循环队列或动态数组来解决这些问题。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐