数据结构之队列的实现(挑战程序设计2)

数据结构之队列的实现

队列的思想在cpu处理多任务是最为常见,先看一个例子。

题目

现有名称为namei且处理时间为timei 的n个任务顺序排成一列,CPU通过循环调度法逐一处理这些任务每个任务最多处理q ms(这个时间成为时间片)。如果q ms之后任务尚未处理完毕,那么该任务将被移动至队伍最末尾,CPU随即开始处理下一个任务。
例子:假设q是100,然后有如下任务队列
A(150)—B(80)—C(200)—D(200)
首先A被处理100ms,然后带着剩余的50ms移动至队列尾。
B(80)—C(200)—D(200)—A(50)
接下来B被处理80ms,在第180ms时完成处理从队列中消失。
C(200)—D(200)—A(50)
依次类推
———————————————————————————————————

输入

n q
name1 time1
name2 time2
… …
第1行输入表示任务数的整数n与表示时间片的整数q,用1个空格隔开。
接下来n行输入各任务的信息。字符串name与timei用1个空格隔开。

输出

按照任务完成的先后顺序输出各任务名以及结束时间,任务名与对应结束时间用空格隔开,每一对任务名与结束时间占1行。

限制

1 ≤ n ≤ 100 000
1 ≤ q ≤ 1000
1 ≤ timei ≤ 50 000
1 ≤ 字符串namei的长度 ≤ 10
1 ≤ timei的和 ≤ 1 000 000

输入示例

5 100
p1 150
p2 80
p3 200
p4 350
p5 20

输出示例

p2 180
p5 400
p1 450
p3 550
p4 800

先看代码

#include<stdio.h>
#include<string.h>
#define LEN 10005

typedef struct PP {
	char name[100];
	int t;
} P;

P Q[LEN];

int head, tail, n;          //n代表总任务数

bool isEmpty() {
	return head == tail;
}

void enqueue(P x) {          //该函数用来向队列尾添加元素
	Q[tail] = x;
	tail = (tail + 1) % LEN;
}

P dequeue() {               //该函数用来从队列前取出元素
	P x = Q[head];
	head = (head + 1) % LEN;
	return x;
}

int min(int a, int b) { return a < b ? a : b; }

int main()
{
	int elaps = 0, c;
	int i, q;                    //q代表的是时间片
	P u;
	scanf("%d %d", &n, &q);
	//按顺序添加任务到队列
	for (i = 1; i <= n ; i++)
	{
		scanf("%s", Q[i].name);
		scanf("%d", &Q[i].t);
	}
	head = 1; tail = n + 1;

	while (tail != head)
	{
		u = dequeue();
		c = min(q, u.t);
		u.t -= c;
		elaps += c;
		if (u.t > 0)
		{
			enqueue(u);
		}
		else
		{
			printf("%s %d\n", u.name, elaps);
		}
	}
	return 0;
}

使用数组可以模拟队列,主要需要以下变量以及函数
1.储存数据的数组:Q
2.用作头指针的head,dequeue每次会取出head所指的元素。
3.指向队列尾的tail,他的值是n+1,每次enqueue会将处理好的数据存储在数据末尾的后边。
4.enqueue(x)函数,向队列中添加元素,注意他是有参的
5.dequeue()函数,用来取出元素的函数。
在程序运行时,首先会从Q的开头取出元素在处理之后用enqueue将其添加到tail所指的位置。这样一次处理下去,知道head与tail相等时,处理完成。

不过这样做首先需要保证数组的长度足够,否则当tail+1是很容易发生数组下标越界。在处理大型数据时,数组的长度可能会十分恐怖
如果想要避免这种情况,则需要将head指针常保持在0,而每次执行完dequeue()之后将所有数据向数组开头移动。缺点是,每次移动会增加O(n)的复杂度。
书中的解决办法时使用环形缓冲区来管理数据。
Alt
可以将其理解为秒针,当tail+1=12超出了数组的范围的时候,就将其置为0。类似于1分钟过去了,又从1秒开始计算。

//对head和tail的操作
head = (head + 1) % MAX      //MAX表示数组元素个数
tail = (tail + 1) % MAX      

这两个表达式会将head和tail超出数组数据个数时将其置为0。

环形缓冲区可以同时以复杂度O(1)实现dequeue和enqueue的操作。

队列以及栈作为两种简单的数据结构值得去认真学习。

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

敲困难的代码猿

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

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

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

打赏作者

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

抵扣说明:

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

余额充值