队列(queue)的基本操作(C实现)

队列

队列,简称队,它是一种操作受限的线性表,其限制在表的一端进行插入,另一端进行删除。可进行插入的一端称为队尾(rear),可进行删除的一端称为队头(front)。向队中插入元素叫入队,新元素进入之后就成为新的队尾元素。从队中删除元素叫出队,元素出队后,其后继结点元素就成为新的队头元素。
在这里插入图片描述
队列可以用数组或者链表的结构实现,但是用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。

代码实现

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

typedef int DataType;

typedef struct Node
{
	struct Node* _next;
	DataType _data;
}Node;

typedef struct Queue
{
	Node* _front;
	Node* _rear;
	size_t _size;
}Queue;

void Init(Queue* q)
{
	q->_front = q->_rear = NULL;
	q->_size = 0;
}

Node* CreatNode(DataType val)
{
	Node* node = (Node*)malloc(sizeof(Node));
	node->_next = NULL;
	node->_data = val;
	return node;
}

void Push(Queue* q, DataType val)
{
	Node* node = CreatNode(val);
	if (q->_front == NULL)
	{
		q->_front = q->_rear = node;
	}
	else
	{
		q->_rear->_next = node;
		q->_rear = node;
	}
	++q->_size;
}

void Pop(Queue* q)
{
	assert(q->_front != NULL);
	Node* next = q->_front->_next;
	free(q->_front);
	q->_front = next;
	if (q->_front == NULL)
	{
		q->_rear = NULL;
	}
	--q->_size;
}

DataType Front(Queue* q)
{
	assert(q->_front != NULL);
	return q->_front->_data;
}

DataType Back(Queue* q)
{
	assert(q->_front != NULL);
	return q->_rear->_data;
}

int Empty(Queue* q)
{
	if (q->_size == 0)
	{
		return 1;
	}
	return 0;
}

size_t Size(Queue* q)
{
	return q->_size;
}

void Destroy(Queue* q)
{
	if (q->_front)
	{
		Node* cur = q->_front;
		while (cur)
		{
			Node* next = cur->_next;
			free(cur);
			cur = next;
		}
		q->_front = q->_rear = NULL;
		q->_size = 0;
	}
}

void Print(Queue* q)
{
	Node* cur = q->_front;
	while (cur)
	{
		printf("%d ", cur->_data);
		cur = cur->_next;
	}
	printf("\n");
}

测试用例

void Test1()
{
	Queue q;
	Init(&q);
	Push(&q, 1);
	Push(&q, 2);
	Push(&q, 3);
	Push(&q, 4);
	Print(&q);

	Pop(&q);
	Pop(&q);
	Pop(&q);
	Pop(&q);
	Print(&q);

	Push(&q, 10);
	Push(&q, 20);
	Push(&q, 30);
	Push(&q, 40);
	Print(&q);

	Destroy(&q);
}

void Test2()
{
	Queue q;
	Init(&q);
	Push(&q, 1);
	Push(&q, 2);
	Push(&q, 3);
	Push(&q, 4);
	Print(&q);

	while (!Empty(&q))
	{
		printf("%d ", Front(&q));
		Pop(&q);
	}
	printf("\n");

	Destroy(&q);
}

在这里插入图片描述
在这里插入图片描述

环形队列

在实际使用中还有一种特殊的队列:循环队列。如操作系统课程讲解生产者消费者模型时就可以使用使用循环队列。环形队列可以使用数组实现,也可以使用循环链表实现。
循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。
在这里插入图片描述
leetcode原题设计循环队列

  • MyCircularQueue(k): 构造器,设置队列长度为 k 。
  • Front: 从队首获取元素。如果队列为空,返回 -1 。
  • Rear: 获取队尾元素。如果队列为空,返回 -1 。
  • enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
  • deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
  • isEmpty(): 检查循环队列是否为空。
  • isFull(): 检查循环队列是否已满。

代码实现

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

typedef struct MyCircularQueue
{
	int* _arr;
	int _front;
	int _rear;
	int _capacity;
} MyCircularQueue;

bool myCircularQueueIsEmpty(MyCircularQueue* obj);
bool myCircularQueueIsFull(MyCircularQueue* obj);

//构造器,设置队列长度为 k 
MyCircularQueue* myCircularQueueCreate(int k)
{
	MyCircularQueue* cq = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
	cq->_arr = (int*)malloc(sizeof(int) * (k + 1));
	cq->_capacity = k + 1;
	cq->_front = cq->_rear = 0;
	return cq;
}

//向循环队列插入一个元素, 如果成功插入则返回真
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
{
	if (myCircularQueueIsFull(obj))
	{
		return false;
	}

	obj->_arr[obj->_rear] = value;
	obj->_rear = (obj->_rear + 1) % obj->_capacity;
	return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj)
{
	if (myCircularQueueIsEmpty(obj))
	{
		return false;
	}

	obj->_front = (obj->_front + 1) % obj->_capacity;
	return true;
}

int myCircularQueueFront(MyCircularQueue* obj)
{
	if (myCircularQueueIsEmpty(obj))
	{
		return -1;
	}
	return obj->_arr[obj->_front];
}

int myCircularQueueRear(MyCircularQueue* obj)
{
	if (myCircularQueueIsEmpty(obj))
	{
		return -1;
	}
	return obj->_arr[(obj->_rear - 1 + obj->_capacity) % obj->_capacity];;
}

//检查循环队列是否为空
bool myCircularQueueIsEmpty(MyCircularQueue* obj)
{
	return obj->_front == obj->_rear;
}

//检查循环队列是否已满
bool myCircularQueueIsFull(MyCircularQueue* obj)
{
	return (obj->_rear + 1) % obj->_capacity == obj->_front;
}

void myCircularQueueFree(MyCircularQueue* obj)
{
	obj->_front = obj->_rear = 0;
	free(obj);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值