Bootstrap

【数据结构】顺序队列与链式队列

1.队列的基本概念

队列是一种逻辑结构,是一种特殊的线性表

  • 只能在固定的两端操作线性表

只要满足上述条件,那么这种特殊的线性表就会呈现一种“先进先出”的逻辑,这种逻辑就被称为队列。

由于约定了只能在线性表固定的两端进行操作,于是给队列这种特殊的线性表的插入删除,起个特殊的名称:

  • 队头:可以删除节点的一端
  • 队尾:可以插入节点的一端
  • 入队:将节点插入到队尾之后,函数名通常为enQueue()
  • 出队:将队头节点从队列中剔除,函数名通常为outQueue()
  • 取队头:取得队头元素,但不出队,函数名通常为front()

1.顺序存储的队列:循环队列

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

#define QUEUE_SIZE 10

typedef struct sq_queue
{
    int data[QUEUE_SIZE];
    int tail;
}sq_queue_t;

// 
sq_queue_t *sq_queue_init(void)
{
    sq_queue_t *my_sq_queue = malloc(sizeof(sq_queue_t));
    
    (my_sq_queue->tail) = -1;
    return my_sq_queue;
}

// 入队
int en_queue(int new_data, sq_queue_t *sq_queue)
{
    // 判断队列是否满了
    if (sq_queue->tail > QUEUE_SIZE - 1)
    {
        printf("队列已满!\n");
        return -1;
    }
    
    (sq_queue->tail)++;
    sq_queue->data[sq_queue->tail] = new_data;
    return 0;
}

// 出队
int out_queue(sq_queue_t *sq_queue)
{
    int i;
    if (sq_queue->tail < 0)
    {
        printf("队列已空!\n");
        return -1;
    }
    int temp = sq_queue->data[0];
    for (i = 0; i < sq_queue->tail; i++)
    { 
        sq_queue->data[i] = sq_queue->data[i+1];
    }
    (sq_queue->tail)--;
    return temp;
}

int main(int argc, char const *argv[])
{
    int i;
    sq_queue_t *my_sq_queue = sq_queue_init();
    if (!my_sq_queue)
    {
        printf("[main] init fail\n");
        return -1;
    }

    for (i = 0; i < 12; i++)
    {
        en_queue(i, my_sq_queue);
    }

    for (i = 0; i < 12; i++)
    {
        printf("出队数据:%d\n", out_queue(my_sq_queue));
    }
    
    return 0;
}


3.链式存储的队列:链式队列

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

typedef struct list_queue
{
    int data;
    struct list_queue *tail;
    struct list_queue *next;
}list_queue_t;

// 初始化链式队列, 定义结构体变量
list_queue_t *list_queue_init(void)
{
    list_queue_t *queue_head = malloc(sizeof(list_queue_t));
    queue_head->next = NULL;
    queue_head->tail = queue_head; // 对尾指针指向头节点,每次插入新的节点需要更新队尾指针

    return queue_head;
}

// 入队--尾插
int in_queue(int new_data, list_queue_t *queue)
{
    list_queue_t *new_node = malloc(sizeof(list_queue_t));
    // 初始化数据域
    new_node->data = new_data;
    new_node->next = NULL;
    new_node->tail = NULL;
    // 把新的节点插入到队尾后面
    queue->tail->next = new_node; 
    // 更新队尾---指向新的节点
    queue->tail = new_node;

    return 0;
}

// 出队--把头节点的下一个节点删除,返回该节点的数据
int out_queue(list_queue_t *queue)
{
    // 判断队列是否为空
    if (!queue->next)
    {
        printf("队列已空!\n");
        return -1;
    }
    
    // 定义指针p指向待删除的节点--也就是头节点的下一个节点
    list_queue_t *p = queue->next;
    // 备份待删除节点的数据
    int temp = p->data;
    // 将头节点的next指针指向待删除节点的下一个节点--删除队首
    queue->next = p->next;

    p->next = NULL;
    free(p);

    return temp;
}

#define IN_QUEUE_NUM 5
int main(int argc, char const *argv[])
{
    unsigned char i;
    list_queue_t *head_queue = list_queue_init();
    for (i = 0; i < IN_QUEUE_NUM; i++)
    {
        in_queue(i, head_queue);
    }
    
    for (i = 0; i < IN_QUEUE_NUM + 1; i++)
    {
        printf("出队的数据:%d\n", out_queue(head_queue));
    }
    

    return 0;
}

/*
执行结果:
    出队的数据:0
    出队的数据:1
    出队的数据:2
    出队的数据:3
    出队的数据:4
    队列已空!
    出队的数据:-1

*/

;