?队列FIFO
#include<stdio.h>
#include<stdlib.h> // 添加此头文件以使用 malloc 和 free 函数
typedef int DataType;
// 定义队列结点结构体
struct QueueNode {
DataType data; // 数据
struct QueueNode* next; // 指向下一个结点的指针
};
// 定义队列结构体
struct Queue {
struct QueueNode* head; // 队列头指针
struct QueueNode* tail; // 队列尾指针
int size; // 队列大小
};
// 入队操作
void QueueEnqueue(struct Queue* que, DataType dt) {
// 创建新结点
struct QueueNode* vtx = (struct QueueNode*)malloc(sizeof(struct QueueNode));
vtx->data = dt;
vtx->next = NULL;
// 将新结点添加到队列尾部
if (que->tail) {
que->tail->next = vtx;
} else {
que->head = vtx;
}
que->tail = vtx;
++que->size;
}
// 出队操作
void QueueDequeue(struct Queue* que) {
// 保存队列头结点的指针
struct QueueNode* temp = que->head;
// 更新队列头指针
que->head = temp->next;
free(temp); // 释放原头结点的内存
--que->size;
// 如果队列为空,更新队列尾指针
if (que->size == 0) {
que->tail = NULL;
}
}
// 获取队列头结点的数据
DataType QueueGetFront(struct Queue* que) {
return que->head->data;
}
int main() {
// 创建一个队列
struct Queue queue;
queue.head = NULL;
queue.tail = NULL;
queue.size = 0;
// 入队操作
QueueEnqueue(&queue, 10);
QueueEnqueue(&queue, 20);
QueueEnqueue(&queue, 30);
// 打印队列头结点的数据
printf("Front element: %d\n", QueueGetFront(&queue));
// 出队操作
QueueDequeue(&queue);
// 打印队列头结点的数据
printf("Front element: %d\n", QueueGetFront(&queue));
return 0;
}
例题1
动物收容所。有家动物收容所只收容狗与猫,且严格遵守“先进先出”的原则。在收养该收容所的动物时,收养人只能收养所有动物中“最老”(由其进入收容所的时间长短而定)的动物,或者可以挑选猫或狗(同时必须收养此类动物中“最老”的)。换言之,收养人不能自由挑选想收养的对象。请创建适用于这个系统的数据结构,实现各种操作方法,比如
enqueue
、dequeueAny
、dequeueDog
和dequeueCat
。允许使用Java内置的LinkedList数据结构。
enqueue
方法有一个animal
参数,animal[0]
代表动物编号,animal[1]
代表动物种类,其中 0 代表猫,1 代表狗。
dequeue*
方法返回一个列表[动物编号, 动物种类]
,若没有可以收养的动物,则返回[-1,-1]
。示例1:
输入: ["AnimalShelf", "enqueue", "enqueue", "dequeueCat", "dequeueDog", "dequeueAny"] [[], [[0, 0]], [[1, 0]], [], [], []] 输出: [null,null,null,[0,0],[-1,-1],[1,0]]示例2:
输入: ["AnimalShelf", "enqueue", "enqueue", "enqueue", "dequeueDog", "dequeueCat", "dequeueAny"] [[], [[0, 0]], [[1, 0]], [[2, 1]], [], [], []] 输出: [null,null,null,null,[2,1],[0,0],[1,0]]说明:
- 收纳所的最大容量为20000
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int animalNum;
int animalType;
} Animal;
typedef struct Node {
Animal animal;
struct Node* next;
} Node;
typedef struct {
Node* front;
Node* rear;
} Queue;
typedef struct {
Queue* catQueue;
Queue* dogQueue;
} AnimalShelter;
Queue* createQueue() {
Queue* queue = (Queue*)malloc(sizeof(Queue));
queue->front = NULL;
queue->rear = NULL;
return queue;
}
int isEmpty(Queue* queue) {
return (queue->front == NULL);
}
void enqueue(Queue* queue, Animal animal) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->animal = animal;
newNode->next = NULL;
if (isEmpty(queue)) {
queue->front = newNode;
queue->rear = newNode;
} else {
queue->rear->next = newNode;
queue->rear = newNode;
}
}
Animal dequeue(Queue* queue) {
if (isEmpty(queue)) {
Animal emptyAnimal = {-1, -1};
return emptyAnimal;
}
Node* temp = queue->front;
Animal animal = temp->animal;
queue->front = queue->front->next;
if (queue->front == NULL) {
queue->rear = NULL;
}
free(temp);
return animal;
}
AnimalShelter* animalShelterCreate() {
AnimalShelter* shelter = (AnimalShelter*)malloc(sizeof(AnimalShelter));
shelter->catQueue = createQueue();
shelter->dogQueue = createQueue();
return shelter;
}
void animalShelterEnqueue(AnimalShelter* shelter, Animal animal) {
if (animal.animalType == 0) { // Cat
enqueue(shelter->catQueue, animal);
} else if (animal.animalType == 1) { // Dog
enqueue(shelter->dogQueue, animal);
}
}
// 出队任意类型的最早进入收容所的动物
Animal animalShelterDequeueAny(AnimalShelter* shelter) {
if (!isEmpty(shelter->catQueue) && !isEmpty(shelter->dogQueue)) {
// 如果收容所中既有猫又有狗,比较它们的进入时间,选择较早进入的动物类型
Node* catFront = shelter->catQueue->front;
Node* dogFront = shelter->dogQueue->front;
if (catFront->animal.animalNum < dogFront->animal.animalNum) {
return dequeue(shelter->catQueue);
} else {
return dequeue(shelter->dogQueue);
}
} else if (!isEmpty(shelter->catQueue)) {
// 如果只有猫,出队最早进入收容所的猫
return dequeue(shelter->catQueue);
} else if (!isEmpty(shelter->dogQueue)) {
// 如果只有狗,出队最早进入收容所的狗
return dequeue(shelter->dogQueue);
} else {
// 如果收容所为空,返回一个空的Animal结构体表示没有动物可出队
Animal emptyAnimal = {-1, -1};
return emptyAnimal;
}
}
Animal animalShelterDequeueCat(AnimalShelter* shelter) {
return dequeue(shelter->catQueue);
}
Animal animalShelterDequeueDog(AnimalShelter* shelter) {
return dequeue(shelter->dogQueue);
}
int main() {
AnimalShelter* shelter = animalShelterCreate();
Animal animal1 = {0, 0}; // Cat
Animal animal2 = {1, 0}; // Cat
Animal animal3 = {2, 1}; // Dog
animalShelterEnqueue(shelter, animal1);
animalShelterEnqueue(shelter, animal2);
animalShelterEnqueue(shelter, animal3);
// Dequeue the oldest animal of any type
Animal oldestAnimal1 = animalShelterDequeueAny(shelter);
printf("Dequeued animal: animalNum = %d, animalType = %d\n", oldestAnimal1.animalNum, oldestAnimal1.animalType);
// Dequeue the oldest cat
Animal oldestCat = animalShelterDequeueCat(shelter);
printf("Dequeued cat: animalNum = %d, animalType = %d\n", oldestCat.animalNum, oldestCat.animalType);
// Dequeue the oldest dog
Animal oldestDog = animalShelterDequeueDog(shelter);
printf("Dequeued dog: animalNum = %d, animalType = %d\n", oldestDog.animalNum, oldestDog.animalType);
return 0;
}
?例题2
写一个?
RecentCounter
?类来计算特定时间范围内最近的请求。请你实现?
RecentCounter
?类:
RecentCounter()
?初始化计数器,请求数为 0 。int ping(int t)
?在时间?t
?添加一个新请求,其中?t
?表示以毫秒为单位的某个时间,并返回过去?3000
?毫秒内发生的所有请求数(包括新请求)。确切地说,返回在?[t-3000, t]
?内发生的请求数。保证?每次对?
ping
?的调用都使用比之前更大的?t
?值。示例 1:
输入: ["RecentCounter", "ping", "ping", "ping", "ping"] [[], [1], [100], [3001], [3002]] 输出: [null, 1, 2, 3, 3] 解释: RecentCounter recentCounter = new RecentCounter(); recentCounter.ping(1); // requests = [1],范围是 [-2999,1],返回 1 recentCounter.ping(100); // requests = [1, 100],范围是 [-2900,100],返回 2 recentCounter.ping(3001); // requests = [1, 100, 3001],范围是 [1,3001],返回 3 recentCounter.ping(3002); // requests = [1, 100, 3001, 3002],范围是 [2,3002],返回 3提示:
1 <= t <= 109
- 保证每次对?
ping
?调用所使用的?t
?值都?严格递增- 至多调用?
ping
?方法?104
?次
#include <stdio.h>
#define MAX_SIZE 3002
typedef struct {
int queue[MAX_SIZE];
int front;
int rear;
} RecentCounter;
// 初始化计数器
RecentCounter* recentCounterCreate() {
RecentCounter* counter = (RecentCounter*)malloc(sizeof(RecentCounter));
counter->front = 0;
counter->rear = -1;
return counter;
}
// 添加新请求并返回过去3000毫秒内的请求数
int ping(RecentCounter* counter, int t) {
counter->rear = (counter->rear + 1) % MAX_SIZE;
counter->queue[counter->rear] = t;
int startTime = t - 3000;
int count = 0;
int i = counter->front;
while (counter->queue[i] < startTime) {
i = (i + 1) % MAX_SIZE;
}
while (i != (counter->rear + 1) % MAX_SIZE) {
count++;
i = (i + 1) % MAX_SIZE;
}
return count;
}
int main() {
RecentCounter* counter = recentCounterCreate();
printf("%d\n", ping(counter, 1)); // requests = [1],范围是 [-2999,1],返回 1
printf("%d\n", ping(counter, 100)); // requests = [1, 100],范围是 [-2900,100],返回 2
printf("%d\n", ping(counter, 3001)); // requests = [1, 100, 3001],范围是 [1,3001],返回 3
printf("%d\n", ping(counter, 3002)); // requests = [1, 100, 3001, 3002],范围是 [2,3002],返回 3
return 0;
}
例题3
给你一个整数数组?
nums
,有一个大小为?k
?的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的?k
?个数字。滑动窗口每次只向右移动一位。返回?滑动窗口中的最大值?。
示例 1:
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3 输出:[3,3,5,5,6,7] 解释: 滑动窗口的位置 最大值 --------------- ----- [1 3 -1] -3 5 3 6 7 3 1 [3 -1 -3] 5 3 6 7 3 1 3 [-1 -3 5] 3 6 7 5 1 3 -1 [-3 5 3] 6 7 5 1 3 -1 -3 [5 3 6] 7 6 1 3 -1 -3 5 [3 6 7] 7示例 2:
输入:nums = [1], k = 1 输出:[1]提示:
1 <= nums.length <= 105
-104?<= nums[i] <= 104
1 <= k <= nums.length
#include <stdio.h>
#include <stdlib.h>
int* maxSlidingWindow(int* nums, int numsSize, int k, int* returnSize) {
int q[numsSize]; // 双端队列,用于保存窗口中的元素索引
int left = 0, right = 0; // 队列的头部和尾部索引
int i = 0;
// 遍历窗口中的前 k 个元素
for (i = 0; i < k; ++i) {
// 维护队列的性质:保持队列中的元素按照从大到小的顺序排列
while (left < right && nums[i] >= nums[q[right - 1]]) {
right--;
}
q[right++] = i; // 将当前元素索引加入队列
}
*returnSize = 0;
int* ans = malloc(sizeof(int) * (numsSize - k + 1)); // 分配存储结果的数组
ans[(*returnSize)++] = nums[q[left]]; // 将窗口中的最大值加入结果数组
int j = 0;
// 遍历窗口中的剩余元素
for (j = k; j < numsSize; ++j) {
// 维护队列的性质:保持队列中的元素按照从大到小的顺序排列
while (left < right && nums[j] >= nums[q[right - 1]]) {
right--;
}
q[right++] = j; // 将当前元素索引加入队列
// 检查队列头部的元素是否仍在窗口内,如果不在则移除
while (q[left] <= j - k) {
left++;
}
ans[(*returnSize)++] = nums[q[left]]; // 将窗口中的最大值加入结果数组
}
return ans;
}
int main() {
int nums[] = {1, 3, -1, -3, 5, 3, 6, 7};
int k = 3;
int numsSize = sizeof(nums) / sizeof(nums[0]);
int returnSize;
int* result = maxSlidingWindow(nums, numsSize, k, &returnSize);
int i = 0;
for (i = 0; i < returnSize; i++) {
printf("%d ", result[i]);
}
printf("\n");
free(result);
return 0;
}