队列

队列

1. 基本概念

队列(Queue)是一个重要的数据结构,它具有以下核心特征:

  • 是一种线性数据结构
  • 遵循先进先出(FIFO)的原则
  • 只有两种主要操作:入队(在末尾添加)和出队(从开头删除)

队列的基本结构

一个队列包含以下关键部分:

  • 队头(front):最先进入队列的元素位置
  • 队尾(rear):最后进入队列的元素位置
  • 队列中的元素按顺序排列
    image-20250201223717448

2. 实现

image-20250201222650664

共五个程序文件 sequeue.h、linkqueue.h、sequeue.c、linkqueue.c、main.c,包括了顺序队列和链式队列。

sequeue.h

typedef int data_t;

#define N 5     // 队列长度

typedef struct 
{
    data_t data[N];                 // 队列
    int front, rear;                // 队头、队尾    
} sequene_struct, *sequeue;

sequeue sequeue_create();           // 创建队列
int sequeue_clear(sequeue q);       // 清空队列
int sequeue_empty(sequeue q);       // 判断队列是否为空
int sequeue_full(sequeue q);        // 判断队列是否已满
int sequeue_enqueue(sequeue q, data_t x);       // 入队
data_t sequeue_dequeue(sequeue q);              // 出队
int sequeue_show(sequeue q);                    // 显示队列
int sequeue_free(sequeue *q);                   // 释放队列

linkqueue.h

typedef int data_t;

typedef struct node_t
{
    data_t data;                 // 数据域
    struct node_t *next;        // 指针域
} queuenode_struct, *queuenode; // 队列结点结构体类型定义

typedef struct
{
    queuenode front, rear;
} linkqueue_struct,*linkqueue;  // 队列结构体类型定义

linkqueue linkqueue_create();                     // 创建队列
int linkqueue_empty(linkqueue q);                 // 判断队列是否为空
int linkqueue_enqueue(linkqueue q, data_t x);     // 入队
data_t linkqueue_dequeue(linkqueue q);            // 出队
int linkqueue_show(linkqueue q);                  // 遍历队列
int linkqueue_free(linkqueue *q);                 // 释放队列

sequeue.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sequeue.h"


/**
  * @name 	sequeue_create()
  * @brief	创建顺序队列函数,长度为 N ,初始化数据为 0
  * @param  无
  * @retval 队列地址
  */
sequeue sequeue_create()
{
    // 1. 申请空间给队列
    sequeue q = (sequeue)malloc(sizeof(sequene_struct));
    if (q == NULL)
    {
        printf("sequeue create error\n");
    }

    // 2. 初始化队列
    memset(q->data, 0, N*sizeof(data_t));
    q->front = q->rear = 0;

    return q;
}

/**
  * @name 	sequeue_clear()
  * @brief	顺序队列清空函数,长度为 N
  * @param  q 队列地址
  * @retval 0 清空成功, -1 清空失败
  */
 int sequeue_clear(sequeue q)
{
    // 1. 判断队列是否存在
    if (q ==  NULL)
    {
        printf("sequeue is invalid\n");
        return -1;
    }

    // 2. 清空队列
    q->front = q->rear = 0;
    return 0;
}   

/**
  * @name 	sequeue_empty()
  * @brief	判断队列是否为空
  * @param  q 队列地址
  * @retval 1 队列为空, 0 队列不为空
  */
int sequeue_empty(sequeue q)
{
    // 1. 判断队列是否存在
    if (q == NULL)
    {
        printf("sequeue is invalid\n");
        return 0;
    }

    // 2. 判断队列是否为空
    return q->front == q->rear ? 1 : 0;
}

/**
  * @name 	sequeue_full()
  * @brief	判断队列是否为满
  * @param  q 队列地址
  * @retval 1 队列为满, 0 队列不为满
  */
int sequeue_full(sequeue q)
{
    // 1. 判断队列是否存在
    if (q == NULL)
    {
        printf("sequeue is invalid\n");
        return 0;
    }

    // 2. 判断队列是否为满
    return q->front == (q->rear+1)%N ? 1 : 0;
}

/**
  * @name 	sequeue_enqueue()
  * @brief	入队函数
  * @param  q 队列地址
  * @param  x 入队数据
  * @retval 0 入队成功, -1 入队失败
  */
 int sequeue_enqueue(sequeue q, data_t x)
 {
     // 1. 判断队列是否存在
     if (q == NULL)
     {
         printf("sequeue is invalid\n");
         return -1;
     }

     // 2. 判断队列是否为满
     if (q->front == (q->rear + 1)%N)
     {
         printf("sequeue is full\n");
         return -1;
     }

     // 3. 入队
    q->data[q->rear] = x;
    q->rear = (q->rear + 1)%N;

    return 0;
 }

/**
  * @name 	sequeue_enqueue()
  * @brief	入队函数
  * @param  q 队列地址
  * @param  x 入队数据
  * @retval 0 入队成功, -1 入队失败
  */
 data_t sequeue_dequeue(sequeue q)
 {
    data_t x;
     // 1. 判断队列是否存在
     if (q == NULL)
     {
         printf("sequeue is invalid\n");
         return -1;
     }

     // 2. 判断队列是否为空
     if (q->front == q->rear)
     {
         printf("sequeue is empty\n");
         return -1;
     }

     // 3. 出队
     x= q->data[q->front];
     q->front = (q->front + 1)%N;
     return x;
 }

/**
  * @name 	sequeue_enqueue()
  * @brief	遍历输出队列函数
  * @param  q 队列地址
  * @retval NULL
  */
 int sequeue_show(sequeue q)
 {
    // 1. 判断队列是否存在
    if (q == NULL)
    {
        printf("sequeue is invalid\n");
        return -1;
    }

    // 2. 判断队列是否为空
    if (q->front == q->rear)
    {
        printf("sequeue is empty\n");
        return -1;
    }

    // 3. 遍历队列
    if (q->front < q->rear)
    {
        for (int i = q->front; i < q->rear; i++)
        {
            printf("%d POS: %d \n", i, q->data[i]);
        }
    }
    else if (q->front > q->rear)
    {
        for (int i = q->front; i < N; i++)
        {
            printf("%d POS: %d \n", i, q->data[i]);
        }
        for (int i = 0; i < q->rear; i++)
        {
            printf("%d POS: %d \n", i, q->data[i]);
        }
    }
    return 0;
 }

 int sequeue_free(sequeue *q)
 {
    // 1. 判断队列是否存在
    if (*q == NULL)
    {
        printf("sequeue is invalid\n");
        return -1;
    }
    // 2. 释放队列
    free(*q);
    *q = NULL;
    return 0;
 }

linkqueue.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sequeue.h"


/**
  * @name 	sequeue_create()
  * @brief	创建顺序队列函数,长度为 N ,初始化数据为 0
  * @param  无
  * @retval 队列地址
  */
sequeue sequeue_create()
{
    // 1. 申请空间给队列
    sequeue q = (sequeue)malloc(sizeof(sequene_struct));
    if (q == NULL)
    {
        printf("sequeue create error\n");
    }

    // 2. 初始化队列
    memset(q->data, 0, N*sizeof(data_t));
    q->front = q->rear = 0;

    return q;
}

/**
  * @name 	sequeue_clear()
  * @brief	顺序队列清空函数,长度为 N
  * @param  q 队列地址
  * @retval 0 清空成功, -1 清空失败
  */
 int sequeue_clear(sequeue q)
{
    // 1. 判断队列是否存在
    if (q ==  NULL)
    {
        printf("sequeue is invalid\n");
        return -1;
    }

    // 2. 清空队列
    q->front = q->rear = 0;
    return 0;
}   

/**
  * @name 	sequeue_empty()
  * @brief	判断队列是否为空
  * @param  q 队列地址
  * @retval 1 队列为空, 0 队列不为空
  */
int sequeue_empty(sequeue q)
{
    // 1. 判断队列是否存在
    if (q == NULL)
    {
        printf("sequeue is invalid\n");
        return 0;
    }

    // 2. 判断队列是否为空
    return q->front == q->rear ? 1 : 0;
}

/**
  * @name 	sequeue_full()
  * @brief	判断队列是否为满
  * @param  q 队列地址
  * @retval 1 队列为满, 0 队列不为满
  */
int sequeue_full(sequeue q)
{
    // 1. 判断队列是否存在
    if (q == NULL)
    {
        printf("sequeue is invalid\n");
        return 0;
    }

    // 2. 判断队列是否为满
    return q->front == (q->rear+1)%N ? 1 : 0;
}

/**
  * @name 	sequeue_enqueue()
  * @brief	入队函数
  * @param  q 队列地址
  * @param  x 入队数据
  * @retval 0 入队成功, -1 入队失败
  */
 int sequeue_enqueue(sequeue q, data_t x)
 {
     // 1. 判断队列是否存在
     if (q == NULL)
     {
         printf("sequeue is invalid\n");
         return -1;
     }

     // 2. 判断队列是否为满
     if (q->front == (q->rear + 1)%N)
     {
         printf("sequeue is full\n");
         return -1;
     }

     // 3. 入队
    q->data[q->rear] = x;
    q->rear = (q->rear + 1)%N;

    return 0;
 }

/**
  * @name 	sequeue_enqueue()
  * @brief	入队函数
  * @param  q 队列地址
  * @param  x 入队数据
  * @retval 0 入队成功, -1 入队失败
  */
 data_t sequeue_dequeue(sequeue q)
 {
    data_t x;
     // 1. 判断队列是否存在
     if (q == NULL)
     {
         printf("sequeue is invalid\n");
         return -1;
     }

     // 2. 判断队列是否为空
     if (q->front == q->rear)
     {
         printf("sequeue is empty\n");
         return -1;
     }

     // 3. 出队
     x= q->data[q->front];
     q->front = (q->front + 1)%N;
     return x;
 }

/**
  * @name 	sequeue_enqueue()
  * @brief	遍历输出队列函数
  * @param  q 队列地址
  * @retval NULL
  */
 int sequeue_show(sequeue q)
 {
    // 1. 判断队列是否存在
    if (q == NULL)
    {
        printf("sequeue is invalid\n");
        return -1;
    }

    // 2. 判断队列是否为空
    if (q->front == q->rear)
    {
        printf("sequeue is empty\n");
        return -1;
    }

    // 3. 遍历队列
    if (q->front < q->rear)
    {
        for (int i = q->front; i < q->rear; i++)
        {
            printf("%d POS: %d \n", i, q->data[i]);
        }
    }
    else if (q->front > q->rear)
    {
        for (int i = q->front; i < N; i++)
        {
            printf("%d POS: %d \n", i, q->data[i]);
        }
        for (int i = 0; i < q->rear; i++)
        {
            printf("%d POS: %d \n", i, q->data[i]);
        }
    }
    return 0;
 }

 int sequeue_free(sequeue *q)
 {
    // 1. 判断队列是否存在
    if (*q == NULL)
    {
        printf("sequeue is invalid\n");
        return -1;
    }
    // 2. 释放队列
    free(*q);
    *q = NULL;
    return 0;
 }

mian.c

#include <stdio.h>
#include "sequeue.h"
#include "linkqueue.h"

void test_sequeue();
void test_linkqueue();
int main()
{
    test_sequeue();
    test_linkqueue();
    return 0;
}

void test_linkqueue()
{
    printf("******test_linkqueue*****\n");
    linkqueue q = linkqueue_create();
    
    linkqueue_enqueue(q, 10);
    linkqueue_enqueue(q, 90);
    linkqueue_enqueue(q, 30);
  
    linkqueue_show(q);

    linkqueue_enqueue(q, 10);
    linkqueue_enqueue(q, 90);
    linkqueue_enqueue(q, 30);

    printf("linkqueue_dequeue = %d\n", (int)linkqueue_dequeue(q));
    printf("linkqueue_dequeue = %d\n", (int)linkqueue_dequeue(q));

    linkqueue_enqueue(q, 33);
    linkqueue_enqueue(q, 55);
    linkqueue_enqueue(q, 99);

    linkqueue_show(q);
    printf("linkqueue_dequeue = %d\n", (int)linkqueue_dequeue(q));
    printf("linkqueue_dequeue = %d\n", (int)linkqueue_dequeue(q));
    linkqueue_show(q);
    linkqueue_free(&q);
    return;
}
void test_sequeue()
{
    printf("******_test_sequeue_*****\n");
    sequeue q = sequeue_create();
    
    sequeue_enqueue(q, 10);
    sequeue_enqueue(q, 90);
    sequeue_enqueue(q, 30);
  
    sequeue_show(q);
    sequeue_clear(q);

    printf("sequeue_empty(q) = %d\n", sequeue_empty(q));

    sequeue_enqueue(q, 10);
    sequeue_enqueue(q, 90);
    sequeue_enqueue(q, 30);

    printf("sequeue_dequeue = %d\n", (int)sequeue_dequeue(q));
    printf("sequeue_dequeue = %d\n", (int)sequeue_dequeue(q));

    sequeue_enqueue(q, 33);
    sequeue_enqueue(q, 55);
    sequeue_enqueue(q, 99);

    sequeue_show(q);
    sequeue_free(&q);
    return;
}
posted @ 2025-02-01 22:40  Arsun  阅读(42)  评论(0)    收藏  举报