C语言队列和循环队列以及简化自制版本

队列是一种数据存储的结构,一般遵循先进先出规则。

队列

1. 头文件和宏定义

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

#define MAX_SIZE 100
  • #include <stdio.h>:包含标准输入输出库,用于后续的 printf 函数调用,实现输出功能。
  • #include <stdlib.h>:包含标准库,这里虽代码中未直接使用 stdlib.h 里的函数,但为后续可能的动态内存分配等操作做准备。
  • #define MAX_SIZE 100:定义了一个宏 MAX_SIZE,其值为 100,用于表示队列的最大容量。

2. 队列结构体定义

typedef struct {
    int data[MAX_SIZE];
    int front;
    int rear;
} Queue;
  • 定义了一个名为 Queue 的结构体类型,它包含三个成员:
    • int data[MAX_SIZE]:一个大小为 MAX_SIZE 的整数数组,用于存储队列中的元素。
    • int front:表示队列的队首位置,即第一个元素的索引。
    • int rear:表示队列的队尾位置,即下一个可插入元素的位置

3. 队列初始化函数

// 初始化队列
void initQueue(Queue *q) {
    q->front = 0;
    q->rear = 0;
}
  • initQueue 函数的作用是对队列进行初始化。
  • 它接受一个指向 Queue 结构体的指针 q,将队列的 front 和 rear 都初始化为 0,表示队列为空。

4. 判断队列是否为空的函数

// 判断队列是否为空
int isEmpty(Queue *q) {
    return q->front == q->rear;
}

  • isEmpty 函数用于判断队列是否为空。
  • 当队列的 front 和 rear 相等时,说明队列中没有元素,函数返回 1(表示真);否则返回 0(表示假)。

5. 判断队列是否已满的函数

// 判断队列是否已满
int isFull(Queue *q) {
    return q->rear == MAX_SIZE;
}

  • isFull 函数用于判断队列是否已满。
  • 当队列的 rear 等于 MAX_SIZE 时,说明队列已经达到最大容量,函数返回 1(表示真);否则返回 0(表示假)。

6. 入队操作函数

// 入队操作
void enqueue(Queue *q, int item) {
    if (isFull(q)) {
        printf("队列已满,无法入队!\n");
        return;
    }
    q->data[q->rear++] = item;
}

  • enqueue 函数用于将一个元素插入到队列的尾部。
  • 首先调用 isFull 函数判断队列是否已满,如果已满则输出提示信息并返回。
  • 若队列未满,则将元素 item 存储到 data 数组的 rear 位置,然后将 rear 加 1。

7. 出队操作函数

// 出队操作
int dequeue(Queue *q) {
    if (isEmpty(q)) {
        printf("队列为空,无法出队!\n");
        return -1;
    }
    return q->data[q->front++];
}

  • dequeue 函数用于从队列的头部移除并返回一个元素。
  • 首先调用 isEmpty 函数判断队列是否为空,如果为空则输出提示信息并返回 -1。
  • 若队列不为空,则返回 data 数组中 front 位置的元素,然后将 front 加 1。

8. 获取队首元素的函数

c

// 获取队首元素
int getFront(Queue *q) {
    if (isEmpty(q)) {
        printf("队列为空,无队首元素!\n");
        return -1;
    }
    return q->data[q->front];
}

  • getFront 函数用于获取队列的队首元素,但不将其从队列中移除。
  • 首先调用 isEmpty 函数判断队列是否为空,如果为空则输出提示信息并返回 -1。
  • 若队列不为空,则返回 data 数组中 front 位置的元素。

9. 主函数

int main() {
    Queue q;
    initQueue(&q);

    enqueue(&q, 1);
    enqueue(&q, 2);
    enqueue(&q, 3);

    printf("队首元素: %d\n", getFront(&q));

    printf("出队元素: %d\n", dequeue(&q));
    printf("出队元素: %d\n", dequeue(&q));

    return 0;
}

  • main 函数是程序的入口点。
  • 首先定义一个 Queue 类型的变量 q,并调用 initQueue 函数对其进行初始化。
  • 然后依次调用 enqueue 函数将元素 1、2、3 插入到队列中。
  • 接着调用 getFront 函数获取队首元素并输出。
  • 最后两次调用 dequeue 函数进行出队操作,并输出出队的元素。

注意事项

这段代码实现的是一个简单的顺序队列,当队列进行多次出队操作后,front 之前的空间无法再被利用,可能会造成空间的浪费。可以通过循环队列的方式来解决这个问题,让队列空间可以循环使用。

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

#define MAX_SIZE 100

typedef struct {
    int data[MAX_SIZE];
    int front;
    int rear;
} Queue;

// 初始化队列
void initQueue(Queue *q) {
    q->front = 0;
    q->rear = 0;
}

// 判断队列是否为空
int isEmpty(Queue *q) {
    return q->front == q->rear;
}

// 判断队列是否已满
int isFull(Queue *q) {
    return q->rear == MAX_SIZE;
}

// 入队操作
void enqueue(Queue *q, int item) {
    if (isFull(q)) {
        printf("队列已满,无法入队!\n");
        return;
    }
    q->data[q->rear++] = item;
}

// 出队操作
int dequeue(Queue *q) {
    if (isEmpty(q)) {
        printf("队列为空,无法出队!\n");
        return -1;
    }
    return q->data[q->front++];
}

// 获取队首元素
int getFront(Queue *q) {
    if (isEmpty(q)) {
        printf("队列为空,无队首元素!\n");
        return -1;
    }
    return q->data[q->front];
}

int main() {
    Queue q;
    initQueue(&q);

    enqueue(&q, 1);
    enqueue(&q, 2);
    enqueue(&q, 3);

    printf("队首元素: %d\n", getFront(&q));

    printf("出队元素: %d\n", dequeue(&q));
    printf("出队元素: %d\n", dequeue(&q));

    return 0;
}    

循环队列

  1. 结构体定义:CircularQueue 结构体包含一个整数数组 data 用于存储队列元素,front 表示队首位置,rear 表示队尾位置,capacity 表示队列的容量。
  2. 初始化队列:initQueue 函数为队列结构体和存储元素的数组分配内存,并将 front 和 rear 初始化为 0。
  3. 判断队列状态:isEmpty 函数通过比较 front 和 rear 是否相等来判断队列是否为空;isFull 函数通过判断 (rear + 1) % capacity 是否等于 front 来判断队列是否已满。
  4. 入队操作:enqueue 函数将元素插入到队尾,如果队列已满则输出提示信息并返回 0,否则插入元素并更新 rear 的位置,返回 1 表示成功。
  5. 出队操作:dequeue 函数将队首元素取出,如果队列为空则输出提示信息并返回 0,否则取出元素并更新 front 的位置,返回 1 表示成功。
  6. 释放内存:freeQueue 函数用于释放队列结构体和存储元素的数组所占用的内存。
  7. 主函数:在 main 函数中,演示了循环队列的初始化、入队、出队等操作,并在最后释放了队列的内存。
#include <stdio.h>
#include <stdlib.h>

#define QUEUE_SIZE 5

// 定义循环队列结构体
typedef struct {
    int *data;
    int front;
    int rear;
    int capacity;
} CircularQueue;

// 初始化循环队列
CircularQueue* initQueue() {
    CircularQueue *queue = (CircularQueue*)malloc(sizeof(CircularQueue));
    if (queue == NULL) {
        printf("内存分配失败!\n");
        return NULL;
    }
    queue->data = (int*)malloc(QUEUE_SIZE * sizeof(int));
    if (queue->data == NULL) {
        printf("内存分配失败!\n");
        free(queue);
        return NULL;
    }
    queue->front = 0;
    queue->rear = 0;
    queue->capacity = QUEUE_SIZE;
    return queue;
}

// 判断队列是否为空
int isEmpty(CircularQueue *queue) {
    return queue->front == queue->rear;
}

// 判断队列是否已满
int isFull(CircularQueue *queue) {
    return (queue->rear + 1) % queue->capacity == queue->front;
}

// 入队操作
int enqueue(CircularQueue *queue, int item) {
    if (isFull(queue)) {
        printf("队列已满,无法入队!\n");
        return 0;
    }
    queue->data[queue->rear] = item;
    queue->rear = (queue->rear + 1) % queue->capacity;
    return 1;
}

// 出队操作
int dequeue(CircularQueue *queue, int *item) {
    if (isEmpty(queue)) {
        printf("队列为空,无法出队!\n");
        return 0;
    }
    *item = queue->data[queue->front];
    queue->front = (queue->front + 1) % queue->capacity;
    return 1;
}

// 释放队列内存
void freeQueue(CircularQueue *queue) {
    free(queue->data);
    free(queue);
}

int main() {
    CircularQueue *queue = initQueue();
    if (queue == NULL) {
        return 1;
    }

    enqueue(queue, 1);
    enqueue(queue, 2);
    enqueue(queue, 3);

    int item;
    if (dequeue(queue, &item)) {
        printf("出队元素: %d\n", item);
    }
    if (dequeue(queue, &item)) {
        printf("出队元素: %d\n", item);
    }

    enqueue(queue, 4);
    enqueue(queue, 5);

    while (dequeue(queue, &item)) {
        printf("出队元素: %d\n", item);
    }

    freeQueue(queue);
    return 0;
}
    

自制的简易版本循环队列,(包含普通队列功能)

1. 头文件和宏定义

#include<stdio.h>

#define max_size 7

  • #include <stdio.h>:引入标准输入输出库,这样就能使用 printf 函数进行信息输出。
  • #define max_size 7:定义了一个宏 max_size,其值为 7,代表循环队列的最大容量。

2. 全局变量定义

c

int left, right, k;

  • left:代表队列的队首索引。
  • right:代表队列的队尾索引。
  • k:作为一个标志变量,用于区分队列是因为入队操作(k = 1)还是出队操作(k = 0)使得 left 和 right 相等。

3. 判断队列是否为空的函数 iskong

int iskong()
{
    if (left == right && k == 0 || right == -1 && left == -1) // 俩下标相遇,并且是因为取数,则为空 
        return 1;
    return 0;
}

  • 当 left 和 right 相等且 k 为 0(意味着上一次操作是出队),或者 left 和 right 都为 -1(表示队列初始为空)时,函数返回 1,表示队列为空;否则返回 0。

4. 判断队列是否已满的函数 isman

int isman()
{
    if ((right == left) && k == 1 || right == 6 && left == -1) // 俩下标相遇,并且是因为存数,则为满 
        return 1;
    return 0; 
}

  • 当 left 和 right 相等且 k 为 1(意味着上一次操作是入队),或者 right 为 6 且 left 为 -1 时,函数返回 1,表示队列已满;否则返回 0。

5. 入队操作函数 in

int in(int *p, int data)
{
    if (isman())
    {
        printf("队列已满,无法继续存入");
        return 0;
    }

    right++;
    right %= max_size;
    p[right] = data;
    k = 1;
    return data;
}

  • 首先调用 isman 函数判断队列是否已满,若已满则输出提示信息并返回 0。
  • 若队列未满,将 right 加 1 并对 max_size 取模,实现循环效果。
  • 把数据 data 存入队列的 right 位置。
  • 将标志变量 k 设为 1,表示上一次操作是入队。
  • 最后返回存入的数据。

6. 出队操作函数 out

int out(int *q)
{
    if (iskong())
    {
        printf("队列已空,无法继续取出\n");
        return -1;
    }
    ++left;
    left %= max_size;
    k = 0;
    return q[left];
}

  • 首先调用 iskong 函数判断队列是否为空,若为空则输出提示信息并返回 -1。
  • 若队列不为空,将 left 加 1 并对 max_size 取模,实现循环效果。
  • 将标志变量 k 设为 0,表示上一次操作是出队。
  • 最后返回队首元素。

7. 主函数 main

int main()
{
    k = 0;
    int dl[max_size];
    left = -1;
    right = -1;
    in(dl, 0);
    in(dl, 1);
    in(dl, 2);
    in(dl, 3);
    in(dl, 4);
    in(dl, 5);
    in(dl, 6);
    printf("%d ", out(dl));
    printf("%d ", out(dl));
    in(dl, 7);
    in(dl, 8);
    printf("%d ", out(dl));
    printf("%d ", out(dl));
    printf("%d ", out(dl));
    printf("%d ", out(dl));
    printf("%d ", out(dl));
    printf("%d ", out(dl));
    printf("%d ", out(dl));
    return 0;
}

  • 初始化 k 为 0,left 和 right 为 -1,表示队列初始为空。
  • 定义一个大小为 max_size 的数组 dl 作为队列的存储容器。
  • 依次将 0 到 6 这 7 个元素入队。
  • 进行两次出队操作并输出出队元素。
  • 尝试将 7 和 8 入队。
  • 继续进行多次出队操作并输出出队元素。

总函数

#include<stdio.h>

#define max_size 7

int left,right,k;

int iskong()
{
	if(left==right&&k==0||right==-1&&left==-1)//俩下标相遇,并且是因为取数,则为空 
	return 1;
	return 0;
}
int isman()
{
	if((right==left)&&k==1||right==6&&left==-1)//俩下标相遇,并且是因为存数,则为满 
	return 1;
	return 0; 
}

int in(int *p,int data)
{		
if(isman())
{
	printf("队列已满,无法继续存入");
	return 0;
}

	right++;
		right %= max_size;
	p[right] = data;
	k=1;
	return data;
}

int out(int *q)
{
	if(iskong())
	{
		printf("队列已空,无法继续取出\n");
		return -1;
	}
	++left;
	left %= max_size;
		k=0;
	return q[left];

}

int main()
{
	k=0;
	int dl[max_size];
	left = -1;
	right = -1;
	in(dl,0);
	in(dl,1);
	in(dl,2);
		in(dl,3);
		in(dl,4);
		in(dl,5);
		in(dl,6);
	printf("%d ",out(dl));
	printf("%d ",out(dl));
in(dl,7);
in(dl,8);
printf("%d ",out(dl));
	printf("%d ",out(dl));
	printf("%d ",out(dl));
		printf("%d ",out(dl));
		printf("%d ",out(dl));
			printf("%d ",out(dl));
			printf("%d ",out(dl));
	return 0;
}

队列本身就是一种先进先出的普通存储数据结构,所以可以简化很多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LAOLONG-C

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值