循环队列算法

循环队列算法
循环队列算法

前天写了栈的实现,今天到队列了,好像明天要期中考试,还是三科,次奥,考吧考吧,五一三天已经贡献给你们了,考成什么样我也认了,毕竟智商在这里。说好的一天来一发,不要说我水,其实我还真的是水,上个学期数据结构课打酱油,这个学期又自己抱本书从第一页开始恭恭敬敬地学,不敢跳过一个字。估计是脑子里面灌浆了。上学期不认真。前车之鉴,希望筒子们好好的把数据结构学好。希望老夫子还为时不晚。

队列和栈一样也是一种很基本的数据结构,队列的用途很多,下面是两个例子。

第一个例子就是CPU资源的竞争问题。在具有多个终端的计算机系统中,有多个用户需要使用CPU各自运行自己的程序,它们分别通过各自终端向操作系统提出使用CPU的请求,操作系统按照每个请求在时间上的先后顺序,将其排成一个队列,每次把CPU分配给队头用户使用,当相应的程序运行结束,则令其出队,再把CPU分配给新的队头用户,直到所有用户任务处理完毕。

第二个例子就是主机与外部设备之间速度不匹配的问题。以主机和打印机为例来说明,主机输出数据给打印机打印,主机输出数据的速度比打印机打印的速度要快得多,若直接把输出的数据送给打印机打印,由于速度不匹配,显然是不行的。所以解决的方法是设置一个打印数据缓冲区,主机把要打印输出的数据依此写如到这个缓冲区中,写满后就暂停输出,继而去做其它的事情,打印机就从缓冲区中按照先进先出的原则依次取出数据并打印,打印完后再向主机发出请求,主机接到请求后再向缓冲区写入打印数据,这样利用队列既保证了打印数据的正确,又使主机提高了效率。

通过上面的两个例子我们知道队列和栈之间的本质的区别了。栈是遵循先进后出,而队列则是遵循先进先出。由于它的先进先出,导致当队头的元素出来之后,队头的指针会上移,往队尾插入元素的时候队尾的指针也是往上移,这个和我们平时的生活经验可能不一样,以我们平时的生活经验,排队买票,队头的人买完票之后,后面的人会向前补上来,这一补可是所有的人都要往前移动一个位置,这在计算机的队列中就相当于要后面的所有元素都要往前进一个位置,这个开销是很大的,所以,计算机中的队列没有采取这样的方法。但是这样之后另外一个问题又出来了,当把队头的元素移走之后,队头上移,我们知道,队列插入元素是从后面插入的,这就造成了队头前面的内存空出来了,而且还不能用了,因为我们不能把元素从队头插进去。于是乎,聪明的人们想到了循环队列这种东西。当队尾插不进去,队头前面又还有空位的时候,就把队尾下调到队头前面的位置,但记住他还是队尾,如此下去,就不会担心内存的浪费了。下面用图来解释一下:

通过上面的两个图,应该能知道循环队列是怎么实现的了,就多了一个判断,哥哥画图可画了一个多小时。。。。

下面贴出代码,注释详细:

Java代码

1.package 环形数组队列;

2.

3.public class CricleQueue {

4. /*

5. * 对列的长度

6. */

7. private int maxSize;

8.

9. /*

10. * 队列数组

11. */

12. private long[] queueArray;

13.

14. /*

15. * 头下标(指针)

16. */

17. private int front;

18.

19. /*

20. * 尾下标(指针)

21. */

22. private int rear;

23.

24. /*

25. * 队列中元素的个数

26. */

27. private int nElement;

28.

29. /*

30. * 构造方法,初始化各种数据

31. */

32. public CricleQueue(int maxSize) {

33. this.maxSize = maxSize;

34. queueArray = new long[maxSize];

35. rear = -1;

36. front = 0;

37. nElement = 0;

38. }

39.

40. /*

41. * 在队列的尾部插入一个元素

42. */

43. public void insert(long value) {

44. if(rear==maxSize-1){

45. rear = -1;

46. }

47. queueArray[++rear] = value;

48. nElement++;

49. }

50.

51. /*

52. * 删除队头的元素

53. */

54. public long remove() {

55. long temp = queueArray[front++];

56. if(front==maxSize) {

57. front = 0;

58. }

59. nElement--;

60. return temp;

61. }

62.

63.

64. /*

65. * 判断队列是否为空

66. */

67. public boolean isEmpty() {

68. return nElement==0;

69. }

70.

71. /*

72. * 判断队列是否为满

73. */

74. public boolean isFull() {

75. return nElement==maxSize;

76. }

77.

78. /*

79. * 查看队头元素

80. */

81.

82. public long peekF() {

83. return queueArray[front];

84. }

85.

86. /*

87. * 查看元素个数

88. */

89.

90. public int qSize() {

91. return nElement;

92. }

93.

94.

95. public static void main(String[] args) {

96. CricleQueue cq = new CricleQueue(5);

97.

98. System.out.println("队列是否为空:"+cq.isEmpty());

99.

100. //插入元素

101. cq.insert(1);

102. cq.insert(2);

103. cq.insert(3);

104. System.out.println("队列是否满了:"+cq.isFull()); 105. cq.insert(4);

106. cq.insert(5);

107. System.out.println("队列中元素个数:"+cq.qSize()); 108.

109. System.out.println("队列是否满了:"+cq.isFull()); 110. System.out.println("对头的元素为:"+cq.peekF()); 111.

112. //移除两个元素

113. cq.remove();

114. cq.remove();

115. System.out.println("队列中元素个数:"+cq.qSize()); 116.

117. System.out.println("对头的元素为:"+cq.peekF()); 118.

119. //插入两个元素

120. cq.insert(6);

121. cq.insert(7);

122. System.out.println("队列中元素个数:"+cq.qSize()); 123.

124. System.out.println("队列是否满了:"+cq.isFull()); 125.

126. //移除四个元素

127. cq.remove();

128. cq.remove();

129. cq.remove();

130. cq.remove();

131. System.out.println("队列中元素个数:"+cq.qSize()); 132. System.out.println("对头的元素为:"+cq.peekF()); 133.

134. }

135.}

输出结果:

Java代码

1.队列是否为空:true

2.队列是否满了:false

3.队列中元素个数:5

4.队列是否满了:true

5.对头的元素为:1

6.队列中元素个数:3

7.对头的元素为:3

8.队列中元素个数:5

9.队列是否满了:true

10.队列中元素个数:1

11.对头的元素为:7

就这样,队列的内存就不会被浪费掉了,只要里面有空的位置你就可以插入元素。

试验 --循环队列的基本操作及应用

数据结构实验报告 ----试验三循环队列的基本操作及应用 一、问题描述: 熟悉并掌握循环队列的相关操作,自己设计程序,实现循环队列的构造、清空、销毁及队列元素的插入和删除等相关操作。 二、数据结构设计: #define MAXQSIZE 10 //最大队列长度 struct SqQueue { QElemType *base; //初始化动态分配存储空间 Int front; // 头指针,若队列不空,只想对列头元素 int rear; //尾指针,若队列不空,指向队列尾元素的 //下一个位置 }; 三、功能设计: 程序中所涉及到的函数如下: Status InitQueue(SqQueue &Q) //构造一个空队列Q Status DestroyQueue(SqQueue &Q) //销毁队列Q,Q不再存在 Status ClearQueue(SqQueue &Q) //将Q清为空队列 Status QueueEmpty(SqQueue Q) //若队列Q为空队列,则 //返回TRUE,否则返回FALSE int QueueLength(SqQueue Q) //返回Q的元素个数,即队列长度Status GetHead(SqQueue Q,QElemType &e)//若队列不空,则用e返回Q的对 //头元素,并返回OK,否则返回ERROR Status EnQueue(SqQueue &Q,QElemType e)//插入元素e为Q的新的队尾元素Status DeQueue(SqQueue &Q,QElemType &e)//若队列不空,则删除Q的队头 //元素,用e返回其值,并返回 //OK,否则返回ERROR Status QueueTraverse(SqQueue Q,void(*vi)(QElemType))//从队头到队尾依次 //对队列Q中每个元素调用函数 //vi()。一旦vi失败,则操作失败四、源程序: // c1.h (程序名) #include #include #include // malloc()等 #include // INT_MAX等 #include // EOF(=^Z或F6),NULL

3 实现队列的入队操作

实现队列的入队操作 函数原型: void insertNode(struct Queue* queue , ElementType value){ } 其中参数queue 是带插入元素的队列指针,后面的value 当然就是需要插入的值了。 下面写具体的逻辑: int isEmpty(struct Queue* queue){ // 判断队列是否为空,如果为空则返回 1 // 不为空则返回 0 return queue->count == 0; } void insertNode(struct Queue* queue , ElementType value){ // 创建一个新的节点 node ,并让这个节点的值等于value , next指针指向NULL struct Node* node = newNode(value , NULL); // 如果队列为空 if(isEmpty(queue)){ // 让 front 指针指向新的节点 node queue->front = node; //让 tail 指针指向新的节点 node queue->tail = node; /* * 大家可以回想以想在图示的过程中,当队列 * 为空的时候,我是没画 front 指针和 tail指针的 * 这个时候让 font 和 tail 都指向空就好了,也就是初始化 * 的时候让 font 和 tail 都指向了 NULL(空) * NULL 其实是一个宏,它的值是 0(整型 0) * 当队列中添加了第一个元素的时候我才画出来 * font 指针和 tail 指针,并且让 font 和 tail * 都指向了第一个节点,就想现在,如果队列在添加节点的时候为空 * 则执行上面的操作 * */ }else{ //如果队列不为空 /* * 大家再看一下图示过程中,当队列中有一个节点的时候,

操作系统复习试题

洛阳师范学院2014—2015学年第一学期期末考试试卷(A) 1.在个人计算机上运行的系统一般是()。 A)手工操作 B)单道批处理 C)多道批处理 D)多用户分时系统 2.早期OS设计追求的主要目标是()。 A)系统的效率 B)用户的方便性 C)可移植性 D)可扩充性 3.下列进程状态转换不可能发生的是()。 A)就绪->执行 B)执行->就绪C)执行->阻塞D)阻塞->执行4.从资源管理角度看,进程调度属于()。 A)I/O管理 B)文件管理 C)处理机管理 D)存储器管理 5.用P、V操作实现进程同步时,信号量的初值一般为()。 A)-1 B)1 C)0 D)任意值 6.如果系统内存不足,可将进程调至外存挂起。从调度的角度看,该行为属于()。 A)低级调度B)中级调度C)高级调度D)处理机调度 7.在一次磁盘I/O过程中,时间消耗最长的阶段是()。 A)寻道 B)旋转 C)传输 D)启动 8.在动态分区分配中,会导致空闲分区链首聚集碎片的是()。 A)最佳适应算法B)首次适应算法C)循环首次适应算法D)最坏适应算法9.下述I/O控制方法中,CPU干预次数最少的是()。 A)程序I/O B)中断I/O C)DMA方式D)通道方式 10.下述文件存储方式中,文件读取速度最快的是()。 A)连续存储 B)链式存储 C)索引存储 D)多级索引存储 1.操作系统设计的目标包括、、可扩充性和开放性。 2.操作系统中,资源分配的基本单位是。 3.不满足“让权等待”准则的信号量机制是。 4.在页式和段式存储管理系统中,存储管理有利于提高内存利用率,存储管理有利于满足用户需求。 5.在高响应比优先调度算法中,进程优先权最初与有关,并随着的增加而增大。

C语言之循环队列的基本操作

1):循环队列的基本操作 #include #include #define OK 1 #define ERROR 0 typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等typedef int QElemType; #define MAXQSIZE 100 // 最大队列长度(对于循环队列,最大队列长度要减1) typedef struct { QElemType *base; // 初始化的动态分配存储空间 int front; // 头指针,若队列不空,指向队列头元素 int rear; // 尾指针,若队列不空,指向队列尾元素的下一个位置 }SqQueue; Status InitQueue(SqQueue &Q) { Q.base=(QElemType *)malloc(MAXQSIZE*sizeof(QElemType)); if(!Q.base) { return ERROR; } Q.front=Q.rear=0; return OK; } Status EnQueue(SqQueue &Q,QElemType e) { if((Q.rear+1)%MAXQSIZE==Q.front) return ERROR; Q.base[Q.rear]=e; Q.rear=(Q.rear+1)%MAXQSIZE; return OK; } Status DeQueue(SqQueue &Q, QElemType &e) { if(Q.front==Q.rear) return ERROR; e=Q.base[Q.front]; Q.front=(Q.front+1)%MAXQSIZE; return OK; }

操作系统实验_首次适应算法与循环首次适应算法

学号P7******* 专业计算机科学与技术姓名 实验日期2017.11.16 教师签字成绩 实验报告 【实验名称】首次适应算法和循环首次适应算法 【实验目的】 学会主存空间分配与回收的基本方法首次适应算法和循环首次适应算法。 【实验原理】 理解在连续分区动态的存储管理方式下,如何实现贮存空间的分配与回收。 采用可变式分区管理,使用最佳适应算法实现主存空间的分配与回收。 采用可变式分区管理,使用最坏适应算法实现主存空间的分配与回收。 数据结构: 1、bool ROM[N]; //定义主存信息,如果内存被占用,则标记为1,否则标记为0,设置内存单元为1024 2、pcb num[20];//定义作业数组,最大支持20个作业 3、typedef struct Pcb //定义作业结构体,包括名称,开始时间,大小,是否执行状态 { char name[10]; int start; int size; int state=0; } pcb; typedef struct Free_rom //空闲区结构体

{ int num; int start; int end; int space; } Free_room; Free_rom free_rom[100];//设置空闲区数组为100个 主要函数 void init();//初始化信息,包括初始化内存信息,和初始化作业队列 void insert_pcb1(pcb &a);插入作业函数,首次适应算法,如果有适合的就插入,无合适输出‘插入失败’ void insert_pcb1(pcb &a);插入作业函数,循环首次适应算法,如果有适合的就插入,无合适输出‘插入失败’ void Delete(pcb &a)//删除作业信息,包括修改内存状态修改作业状态并对作业进行初始化 void show();//显示信息 void find_free_rom() //寻找空闲区 算法流程图

顺序队的基本操作

上机实验报告 学院:计算机与信息技术学院 专业:计算机科学与技术(师范)课程名称:数据结构 实验题目:顺序队的基本操作 班级序号:师范1班 学号: 2731 学生姓名:邓雪 指导教师:杨红颖 完成时间: 2015年12月25号

一、实验目的: 1.熟悉掌握队的定义、结构及性质;? 2. 熟练掌握循环队列的操作及应用,掌握循环队列的入队和出队等基本操作。? 3. 加深对队列结构的理解,逐步培养解决实际问题的编程能力 二、实验环境: Windows Microsoft Visual c++ 三、实验内容及要求: 掌握队列的概念及性质,并建立顺序队,实现如下功能: 1.建立一个顺序队 2.输出队 3.求队长 4.判队空 5.取队头 6.入队 7.出队 8. 清空栈 四、概要设计: 1、通过循环,由键盘输入一串数据。创建并初始化一个顺序队。 2、编写实现相关功能函数,完成子函数模块如下。 3、调用子函数,实现菜单调用功能,完成顺序表的相关操作。

#include <> #include <> #define maxsize 1024 typedef int datatype; //定义结构体 typedef struct { datatype data[maxsize]; int front,rear; }sequeue; sequeue *sq; //建立顺序队 sequeue *SET() { sequeue *sq; datatype x; sq=(sequeue *)malloc(sizeof(sequeue)); sq->front=maxsize-1; sq->rear=maxsize-1; printf("请输入要存入的结点值(以0结尾)\n"); scanf("%d",&x); while(x!=0) { sq->rear=(sq->rear+1)%maxsize; sq->data[sq->rear]=x; scanf("%d",&x); } printf("顺序队输入成功\n\n"); return sq; }

操作系统习题

一、选择题 1.在三种基本类型的操作系统中,都设置了进程调度,在批处理系统中还应设置作业调度;在分时系统中除了设置进程调度,通常还设置中级调度,在多处理机系统中则还需设置剥夺调度。 2.在面向用户的调度准则中,截止时间的保证是选择实时调度算法的重要准则,响应时间快是选择分时系统中调度算法的重要准则,平均周转时间短是批处理系统中选择作业调度算法的重要准则,而优先权高的作业能获得优先服务准则则是为了照顾紧急作业用户的要求而设置的。 3.作业调度是从处于后备状态的队列中选取作业投入运行,周转时间是指作业进入系统到作业完成所经过的时间间隔,时间片轮转算法不适合作业调度。 4.下列算法中,FCFS算法只能采用非抢占调度方式,时间片轮转法只能采用抢占调度方式,而其余的算法既可采用抢占方式也可采用非抢占方式。 5.我们如果为每一个作业只建立一个进程,则为了照顾短作业用户,应采用短作业优先;为照顾紧急作业的用户,应采用基于优先权的剥夺调度算法;为能实现人机交互作用应采用时间片轮转法;为了兼顾短作业和长时间等待的用户,应采用高响应比优先;为了使短作业、长作业及交互作业用户都比较满意,应采用多级反馈队列调度算法;为了使平均周转时间最短,应采用短作业优先算法。 6.下列调度方式和算法中,最容易引起进程长期等待的是抢占式静态优先权优先算法。 7.下列选项中,降低进程优先级的最合理的时机是进程的时间片用完。 8.支持多道程序设计的操作系统在运行过程中,不断地选择新进程运行来实现CPU的共享,但其中有新进程进入就绪队列不是引起操作系统选择新进程的直接原因。 9.从下面关于优先权大小的论述中,选择一条正确的论述。 (6)在动态优先权时,随着进程执行时间的增加,其优先权降低。 10.假设就绪队列中有10个进程,以时间片轮转方式进行进程调度,时间片大小为300ms,CPU进行进程切换要花费10ms,则系统开销所占的比率约为%3,若就绪队列中进程的个数增加到20个,其余条件不变,则系统开销所占的比率将

循环首次适应的动态分区分配算法模拟

课程设计报告 课程设计题目:循环首次适应的动态分区分配算法模拟 专业:计算机科学与技术 班级:10204102 姓名:谱 学号: 10204102 指导教师:高小辉 2013年1月11 日

目录 一.循环首次适应算法 (3) 1. 概述 (3) 2.需求分析 (3) 二.实验指导 (4) 1.基本思想 (4) 2.数据结构 (4) 三.运行环境 (6) 四.流程图 (6) 五.循环首次适应算法代码 (5) 六.调试结果 (11) 七、总结 (14) 八.参考文献 (14)

一.循环首次适应算法 1.概述: 该算法是由首次适应算法演变而成的。在为进程分配内存空间时,不再是每次都从链首开始查找,而是从上次找到的空闲分区的下一个空闲分区开始查找,直至找到一个能满足要求的空闲分区,从中划出一块的请求大小相等的内存空间分配给作业。为实现该算法,应设置一起始查找指针,用于指示下一次起始查询的空闲分区,并采用循环查找方式,即如果最后一个(链尾)空闲分区的大小仍不能满足要求,则返回到第一个空闲分区,比较大小是否满足,找到后,应调整起始查询指针。 2. 需求分析 了解动态分区分配中使用的数据结构和分配算法,并进一步加深对动态分区存储管理方式及其实现过程的理解。采用首次适应算法的动态分区分配过程alloc()和回收过程free()。 空闲分区通过空闲分区链表来管理,在进行内存分配时,系统优先使用空闲区低端的空间,即每次分配内存空间是总是从低址部分开始进行循环,找到第一个合适的空间,便按作业所需分配的大小分配给作业。 作业完成时,需要释放作业所占空间,此时要考虑到四种情况: (1)回收区与插入点的前一个空闲分区相邻接。此时将二者合并,修改前一 分区的大小。 (2)回收区与插入点的后一空闲分区相邻接,将二者合并,用回收区的首址 作为新空闲区的首址。 (3)回收区同时与插入点的前后两个空闲分区相邻接,三者合并,使用前一空 闲分区的表项和首址。 (4)回收区单独存在。 二、实验指导 1.基本思想 动态分区是指系统不预先划分固定分区,而是在装入程序的时候划分内存区域,使得为程序分配的分区大小恰好等于该程序的需求量,且分区的个数是动态的。显然动态分区有较大的灵活性,较之固定分区能获得好的内存利用率。 2.数据结构 动态分区管理可以用两种数据结构实现,一种是已分配区表和空闲区表,也就是用预先定义好的系统空间来存放空间分配信息。

实验二 栈与队列操作实验题目

实验二栈与队列操作 实验目的: (1)理解栈与队列的结构特征和运算特征,以便在实际问题背景下灵活运用。 (2)了解复杂问题的递归算法设计。 本次实验中,下列实验项目选做一。 1、顺序栈的基本操作 [问题描述] 设计算法,实现顺序栈的各种基本操作 [基本要求] (1)初始化栈s。 (2)从键盘输入10个字符以$结束,建立顺序栈。 (3)从键盘输入1个元素,执行入栈操作。 (4)将栈顶元素出栈。 (5)判断栈是否为空。 (6)输出从栈顶到栈底元素。 要求程序通过一个主菜单进行控制,在主菜单界面通过选择菜单项的序号来调用各功能函数。 2、链栈的基本操作 [问题描述] 设计算法,实现链栈的各种基本操作 [基本要求] (1)初始化栈s。 (2)从键盘输入10个字符以$结束,建立带头结点的链栈。 (3)从键盘输入1个元素,执行入栈操作。 (4)完成出栈操作。 (5)判断栈是否为空。 (6)输出从栈顶到栈底元素。 (7)输出链栈的长度。 要求程序通过一个主菜单进行控制,在主菜单界面通过选择菜单项的序号来调用各功能函数。 3、循环队列的基本操作 [问题描述] 设计算法,实现循环顺序队列的建立、入队、出队等操作。 [基本要求] (1)从键盘输入10个字符以$结束,建立循环队列,并显示结果。 (2)从键盘输入1个元素,执行入队操作,并显示结果。 (3)将队头元素出队,并显示结果。 (4)要求程序通过一个主菜单进行控制,在主菜单界面通过选择菜单项的序号来调用各功能函数。

4、只用尾指针表示的循环链表队列的综合操作 [问题描述] 假设以带头结点的的循环链表表示队列,并且只设一个指针指向队尾元素的结点(注意不设头指针),试编写队列初始化、入队、出队函数。 [基本要求及提示] (1)首先定义链表结点类型。 (2)编写带头结点的循环链表的初始化函数,只用尾指针表示。 (3)编写入队函数、出队函数。 (4)在主函数中编写菜单(1.初始化;2.入队;3.出队;4.退出),调用上述功能函数。 5、用标志域表示队空队满状态的循环队列的综合操作 [问题描述] 要求循环队列不损失一个空间全部都得到利用,设置一个标志域tag,以0和1来区分当队头与队尾指针相同时队列状态的空和满,试编写与此结构相对应的入队和出队操作。 [基本要求及提示] (1)教材中为区分当队头与队尾指针相同时队列状态的空和满,以牺牲一个空间的代价来实现的,空:Q->front==Q->rear,满:(Q->rear+1)%MAXSIZE==Q->front。 (2)本题不损失一个空间全部都得到利用,为此如下定义循环队列类型: Typedef struct { QueueElementType element[MAXSIZE]; int front; int rear; int tag; }SeqQueue; 此时,循环队列空和满的条件分别为: Q->front==Q->rear&&tag==0 和 Q->front==Q->rear&&tag==1 (3)编写入队函数、出队函数。 (4)在主函数中编写菜单(1.入队;2.出队;3.退出),调用上述功能函数。 6、利用辅助数组进行栈的逆置 [问题描述] 利用辅助栈将栈中的元素逆置。 [基本要求及提示] 在主函数中编写菜单(1.入栈;2.出栈;3.逆置;4.退出)调试运行程序。 7、利用辅助栈进行队列的逆置 [问题描述] 利用辅助栈进行队列元素逆置。 [基本要求及提示] 在主函数中编写菜单(1.入队;2.出队;3.逆置;4.退出)调试运行程序。 8、Hanoi塔问题

循环队列的学习解析以及C语言实现

循环队列的学习解析以及C语言实现 首先我们先来了解一下队列的概念:队列是一种先进先出的线性表只能在表头删除在表尾插入,操作系统的作业队列就是队列的一个很好的应用。也有可以在两端均可进行插入和删除操作的队列,称为双端队列,但其用处并没有一般队列广泛。 ADT Queue { 数据对象: D={ai | ai∈ElemSet, i=1,2,...,n, n≥0} 数据关系: R1={ | ai-1, ai ∈D, i=2,...,n} (约定其中a1端为队列头,an端为队列尾) 基本操作: InitQueue(&Q) 初始化队列 DestroyQueue(&Q) 销毁队列 QueueEmpty(Q) 判断队列空否 QueueLength(Q) 求取队长 GetHead(Q, &e) 取对头元素 ClearQueue(&Q) 清空对列 EnQueue(&Q, e) 入队一个元素 DeQueue(&Q, &e) 出队一个元素 QueueTravers(Q, visit())访问队列

}ADT Queue 队列也有两种存储结构,分别是顺序存储和链式存储。 队列的顺序结构和顺序表以及顺序栈的存储结构类似,他们所运用的都是一组地址连续的存储。其中队列需要附设两个整形变量front 和rear 分别指示队列头元素和队列的尾元素的位置。 (1)空队列 (2)a,b,,c 相继入队 由于顺序队列所分配的空间有限,根据队列入队和出队的特点可能发生“假溢出”现象,即队尾元素无法在前移。解决的办法就是将队列抽象成为环状,即循环队列。 循环队列 以下是循环队列的几种主要的操作以及C 语言实现: c b a 5 4 3 2 1 0 Q.rear → Q.fron → Q.rea → Q.fron → { 队空条件:Q.front=Q.rear 队满条件:(Q.rear+1)%MAXQSIZE

栈与队列习题参考答案

习题三参考答案 备注: 红色字体标明的是与书本内容有改动的内容。 一、选择题 1.在栈中存取数据的原则是( B )。 A.先进先出 B. 先进后出 C. 后进后出 D. 没有限制 2.若将整数1、2、3、4依次进栈,则不可能得到的出栈序列是( D )。 A.1234 B. 1324 C. 4321 D. 1423 3.在链栈中,进行出栈操作时(B )。 A.需要判断栈是否满 B. 需要判断栈是否为空 C. 需要判断栈元素的类型 D. 无需对栈作任何差别 4.在顺序栈中,若栈顶指针top指向栈顶元素的下一个存储单元,且顺序栈的最大容量是maxSize,则顺序栈的判空条件是( A )。 A.top==0 B.top==-1 C. top==maxSize D.top==maxSize-1 5.在顺序栈中,若栈顶指针top指向栈顶元素的下一个存储单元,且顺序栈的最大容量是maxSize。则顺序栈的判满的条件是( C )。 A.top==0 B.top==-1 C. top==maxSize D.top==maxSize-1 6.在队列中存取数据元素的原则是( A )。 A.先进先出 B. 先进后出 C. 后进后出 D. 没有限制 7.在循环顺序队列中,假设以少用一个存储单元的方法来区分队列判满和判空的条件,front和rear分别为队首和队尾指针,它们分别指向队首元素和队尾元素的下一个存储单元,队列的最大存储容量为maxSize,则队列的判空条件是(A )。 A.front==rear B. front!=rear C. front==rear+1 D. front==(rear+1)% maxSize 8.在循环顺序队列中,假设以少用一个存储单元的方法来区分队列判满和判空的条件,front和rear分别为队首和队尾指针,它们分别指向队首元素和队尾元素的下一个存储单元,队列的最大存储容量为maxSize,则队列的判满条件是(D )。 A.front==rear B. front!=rear C. front==rear+1 D. front==(rear+1)% maxSize 9.在循环顺序队列中,假设以少用一个存储单元的方法来区分队列判满和判空的条件,front和rear分别为队首 和队尾指针,它们分别指向队首元素和队尾元素的下一个存储单元,队列的最大存储容量为maxSize,则队列的长度是(C )。 A.rear-front B. rear-front+1 C. (rear-front+maxSize)%maxSize D. (rear-front+1)%maxSize 10.设长度为n的链队列采用单循环链表加以表示,若只设一个头指针指向队首元素,则入队操作的时间复杂度 为( B )。 A.O(1) B.O(n) C.O(log2n) D.O(n2) 二、填空题 1.栈是一种操作受限的特殊线性表,其特殊性体现在其插入和删除操作都限制在表尾进行。允许插入和删除 操作的一端称为栈顶,而另一端称为栈底。栈具有后进先出的特点。 2.栈也有两种存储结构,一种是顺序存储,另一种是链式存储;以这两种存储结构存储的栈分别称为顺序 栈和链栈。 3.在顺序栈中,假设栈顶指针top是指向栈顶元素的下一个存储单元,则顺序栈判空的条件是 top==0 ; 栈顶

实验4顺序循环队列基本操作

实验4: 顺序循环队列基本操作 一、实验目的 1.熟悉并能实现顺序循环队列的定义和基本操作。 2.了解用队列解决实际应用问题。 二、实验要求 1.进行队列的基本操作时要注意队列“先进先出”的特性。 2.复习关于栈操作的基础知识。 3.编写完整程序完成下面的实验内容并上机运行。 4.整理并上交实验报告。 三、实验内容 1.任意输入队列长度和队列中的元素值,构造一个队列,对其进行清空、插入新元素、返回队头元素以及删除队头元素操作。 2.约瑟夫环的实现:设有n个人围坐在圆桌周围,现从某个位置i 上的人开始报数,数到m 的人就站出来。下一个人,即原来的第m+1个位置上的人,又从1开始报数,再是数到m的人站出来。依次重复下去,直到全部的人都站出来,按出列的先后又可得到一个新的序列。由于该问题是由古罗马著名的史学家Josephus提出的问题演变而来,所以通常称为 Josephus 问题。 例如:当n=8,m=4,i=1时,得到的新序列为: 4,8,5,2,1,3,7,6 编写程序选择循环队列(也可换为自己熟悉的数据结构)作为存储结构模拟整个过程,并依次输出出列的各人的编号。 3.(选做实验)设停车场内只有一个可停放n辆汽车的狭长通道,且只有一个大门可供汽车进出。汽车在停车场内按车辆到达时间的先后顺序,依次由北向南排列(大门在最南端,最先到达的第一辆车停放在车场的最北端),若车场内已停满n辆汽车,则后来的汽车只能在门外的便道上等候,一旦有车开走,则排在便道上的第一辆车即可开入;当停车场内某辆车要离开时,在它之后开入的车辆必须先退出车场为它让路,待该辆车开出大门外,其它车辆再按原次序进入车场,每辆停放在车场的车在它离开停车场时必须按它停留的时间长短交纳费用。试为停车场编制按上述要求进行管理的模拟程序。 程序编写提示:以栈模拟停车场,以队列模拟车场外的便道,按照从终端读入的输入数据序列进行模拟管理。每一组输入数据包括三个数据项:汽车“到达”或“离去”信息、汽车牌照号码及到达或离去的时刻,对每一组输入数据进行操作后的输出数据为:若是车辆到达,则输出汽车在停车场内或便道上的停车位置;若是车离去,则输出汽车在停车场内停留的时间和应交纳的费用(在便道上停留的时间不收费)。栈以顺序结构实现,队列以链表实现。需另设一个栈,临时停放为给要离去的汽车让路而从停车场退出来的汽车,也用顺序存储结构实现。输入数据按到达或离去的时刻有序。栈中每个元素表示一辆汽车,包含两个数据项:汽车的牌照号码和进入停车场的时刻。

操作系统新鲜题库

1、静态重定位是在作业(2)中进行,而动态重定位是在作业(4)中进行。 (1) 编译过程(2)装入过程(3)修改过程(4)执行过程 2、由连续分配方式发展到分页存储管理方式的主要动力是(1);由分页系统发展到分段系统,进而发展到段页式系统的主要动力是(4)和(5) (1)提高内存利用率(2)提高系统吞吐量(3)满足用户需要(4)更好地满足多道程序运行的需要(5)既满足用户要求,又提高内存利用率 3、首次适应算法中,要求空闲区按(1)的顺序形成空闲分区链;最佳适应算法中,需要按照(3)顺序形成空闲分区链;最坏适应算法是(4)的顺序形成空闲链。 (1)空闲区的起始地址递增(2)空闲区起始地址递减(3)空闲区大小递增(4)空闲区大小递减 4、对外存交换区的管理应以(4)为主要目标,外存文件区的管理应以(2)为主要目标。(1)提供系统吞吐量(2)提供存储空间的利用率(3)降低存储费用(4)提供换入换出速度 5、虚拟存储器管理系统的基础是程序的局部性原理,那么,局部性理论的基本含义是(程序在执行过程中一个较短时期,所执行的指令地址和指令操作数地址分别局限于一定区域),局部性有两种表现形式,分别是(时间局部性)和(空间局部性)。 6、一个计算机系统中,虚拟存储器的最大容量是由(5)确定的,其实际容量是由(4)确定的。 (1)计算机字长(2)内存容量(3)硬盘容量(4)内存和硬盘交换区容量之和(5)计算机的地址结构 7、在请求调页系统中,内存分配有两种策略:(3)和(4),(3)的缺点是可能导致频繁地出现缺页中断而造成cpu利用率下降。 (1)首次适应(2)最佳适应(3)固定分配(4)可变分配 8、请求调页系统中有多种置换算法:选择最先进入内存的页面淘汰的算法称为(1);选择以后不再使用的页面予以淘汰的算法称为(2);选择自上次访问以来所经历时间最长的页面予以淘汰的算法称为(5);选择自某个时刻开始以来,访问次数最少的页面予以淘汰的算法称为(3); (1) FIFO (2)OPT (3)LRU (5)LFU 9、在环保护机构中,操作系统应该处于(1)内,一般应用程序应该处于(2)内,并遵循下面的规则:一个程序可以访问驻留在(5)中的数据;一个程序可以调用驻留在(4)中的服务。最高特权(2)最低特权(3)相同特权(4)相同特权和高特权(5)相同特权和低特权 10、 二:简答题 1、在动态分区分配中,有哪些分区分配算法?应如何将空闲分区链接为空闲分区链? 最先适配算法 循环最先适配算法 最佳适配算法

数据结构第3章 栈与队列习题

第3章栈与队列 一、单项选择题 1.元素A、B、C、D依次进顺序栈后,栈顶元素是,栈底元素是。 A.A B.B C.C D.D 2.经过以下栈运算后,x的值是。 InitStack(s);Push(s,a);Push(s,b);Pop(s,x);GetTop(s,x); A.a B.b C.1 D.0 3.已知一个栈的进栈序列是ABC,出栈序列为CBA,经过的栈操作是。 A.push,pop,push,pop,push,pop B.push,push,push,pop,pop,pop C.push,push,pop,pop,push,pop D.push,pop,push,push,pop,pop 4.设一个栈的输入序列为A、B、C、D,则借助一个栈所得到的序列是。 A.A,B,C,D B.D,C,B,A C.A,C,D,B D.D,A,B,C 5.一个栈的进栈序列是a,b,c,d,e,则栈的不可能的输出序列是。 A.edcba B.decba C.dceab D.abcde 6.已知一个栈的进栈序列是1,2,3,……,n,其输出序列的第一个元素是i,则第j个出栈元素是。 A.i B.n-i C.j-i+1 D.不确定 7.已知一个栈的进栈序列是1,2,3,……,n,其输出序列是p1,p2,…,Pn,若p1=n,则pi的值。 A.i B.n-i C.n-i+1 D.不确定 8.设n个元素进栈序列是1,2,3,……,n,其输出序列是p1,p2,…,p n,若p1=3,则p2的值。 A.一定是2 B.一定是1

C.不可能是1 D.以上都不对 9.设n个元素进栈序列是p1,p2,…,p n,其输出序列是1,2,3,……,n,若p3=1,则p1的值。 A.可能是2 B.一定是1 C.不可能是2 D.不可能是3 10.设n个元素进栈序列是p1,p2,…,p n,其输出序列是1,2,3,……,n,若p3=3,则p1的值。 A.可能是2 B.一定是2 C.不可能是1 D.一定是1 11.设n个元素进栈序列是p1,p2,…,p n,其输出序列是1,2,3,……,n,若p n=1,则p i(1≤i≤n-1)的值。 A.n-i+1 B.n-i C.i D.有多种可能 12.判定一个顺序栈S为空的条件为。 A.S.top= =S.base B.S.top!= S.base C.S.top!= S.base+S.stacksize D.S.top= = S.base+S.stacksize 13.判定一个顺序栈S为栈满的条件是。 A.S.top-S.base= =S.stacksize B.S.top= = S.base C.S.top-S.base!=S.stacksize D.S.top!= S.base 14.链栈与顺序栈相比有一个明显的优点,即。 A.插入操作方便B.通常不会出现栈满的情况 C.不会出现栈空的情况D.删除操作更加方便 15.最不适合用作链栈的链表是。 A.只有表头指针没有表尾指针的循环双链表 B.只有表尾指针没有表头指针的循环双链表 C.只有表尾指针没有表头指针的循环单链表 D.只有表头指针没有表尾指针的循环单链表 16.如果以链表作为栈的存储结构,则退链栈操作时。 A.必须判别链栈是否满B.判别链栈元素的类型 C.必须判别链栈是否空D.对链栈不作任何判别

操作系统第四章习题

一、选择 1. 可变分区存储器管理系统中,若采用最佳适应分配算法,“空闲区表”中的空闲区 可按( A )顺序排列。 A.长度递增 B.长度递减 C.地址递增 D.地址递减 2. 虚拟存储技术是—B—。 A. 扩充内存物理空间技术 B. 扩充内存逻辑地址空间技术 C.扩充外存空间技术 D. 扩充I/O缓冲区技术 3. 很好地解决了“零头”问题的存储管理方法是—A—。 A.分页存储管理方法 B.分段存储管理方法 C.多重分区管理 D.可变式分区管理 4. 系统“抖动”现象的发生是由—B—引起的。 A.交换的信息量过大 B.置换算法选择不当 C.内存容量不足 D.请求分页管理方案 5. 虚拟存储管理系统的基础是程序的—C—理论。 A. 全局性 B. 虚拟性 C. 局部性 D. 动态性 6. 分页系统中页面是为( B )的。 A、用户所感知 B、操作系统所感知 C、编译系统所感知 D、连接装配程序所感知 7.下列—A—存储方式不能实现虚拟存储器。 A.分区 B.页式 C.段式 D.段页式 8. 操作系统处理缺页中断时,选择一种好的调度算法对内存和外存中的信息进行高效地调度,尽可能避免—D—。 A. 碎片 B.CPU空闲 C. 多重中断 D. 抖动 9. 分页式存储管理的主要特点是—C—。 A. 要求处理缺页中断 B. 要求扩充内存容量 C. 不要求作业装入到内存的连续区域 D. 不要求作业全部同时装入内存 10. LRU页面调度算法淘汰—B—的页。 A. 最近最少使用 B. 最近最久未使用 C. 最先进入内存 D. 将来最久使用 11.虚拟存储器实际容量受—B—限制。 A.物理内存大小 B.计算机的地址结构 C.磁盘容量 D.数据存放的绝对地址 12. 分区管理要求对每一个作业都分配—A—的内存单元。 A. 地址连续 B. 若干地址不连续 C. 若干连续的页 D. 若干不连续的帧 13.页面置换算法中—A—不是基于程序执行的局部性理论。 A.先进先出调度算法 B. LRU C. LFU D.最近最不常用调度算法 14. 在存储管理中,采用覆盖与交换技术的目的是—A—。 A. 节省内存空间 B. 物理上扩充内存容量 C. 提高CPU利用率 D. 实现内存共享 15. 分页虚拟存储管理中,缺页中断时,欲调度一页进入内存,内存已无空闲块,如何决定淘汰已在内存的块时,—B—的选择是很重要的。 A. 地址变换 B. 页面调度算法 C. 对换方式 D. 覆盖技术

循环队列算法

前天写了栈的实现,今天到队列了,好像明天要期中考试,还是三科,次奥,考吧考吧,五一三天已经贡献给你们了,考成什么样我也认了,毕竟智商在这里。说好的一天来一发,不要说我水,其实我还真的是水,上个学期数据结构课打酱油,这个学期又自己抱本书从第一页开始恭恭敬敬地学,不敢跳过一个字。估计是脑子里面灌浆了。上学期不认真。前车之鉴,希望筒子们好好的把数据结构学好。希望老夫子还为时不晚。 队列和栈一样也是一种很基本的数据结构,队列的用途很多,下面是两个例子。 第一个例子就是CPU资源的竞争问题。在具有多个终端的计算机系统中,有多个用户需要使用CPU各自运行自己的程序,它们分别通过各自终端向操作系统提出使用CPU的请求,操作系统按照每个请求在时间上的先后顺序,将其排成一个队列,每次把CPU分配给队头用户使用,当相应的程序运行结束,则令其出队,再把CPU分配给新的队头用户,直到所有用户任务处理完毕。 第二个例子就是主机与外部设备之间速度不匹配的问题。以主机和打印机为例来说明,主机输出数据给打印机打印,主机输出数据的速度比打印机打印的速度要快得多,若直接把输出的数据送给打印机打印,由于速度不匹配,显然是不行的。所以解决的方法是设置一个打印数据缓冲区,主机把要打印输出的数据依此写如到这个缓冲区中,写满后就暂停输出,继而去做其它的事情,打印机就从缓冲区中按照先进先出的原则依次取出数据并打印,打印完后再向主机发出请求,主机接到请求后再向缓冲区写入打印数据,这样利用队列既保证了打印数据的正确,又使主机提高了效率。 通过上面的两个例子我们知道队列和栈之间的本质的区别了。栈是遵循先进后出,而队列则是遵循先进先出。由于它的先进先出,导致当队头的元素出来之后,队头的指针会上移,往队尾插入元素的时候队尾的指针也是往上移,这个和我们平时的生活经验可能不一样,以我们平时的生活经验,排队买票,队头的人买完票之后,后面的人会向前补上来,这一补可是所有的人都要往前移动一个位置,这在计算机的队列中就相当于要后面的所有元素都要往前进一个位置,这个开销是很大的,所以,计算机中的队列没有采取这样的方法。但是这样之后另外一个问题又出来了,当把队头的元素移走之后,队头上移,我们知道,队列插入元素是从后面插入的,这就造成了队头前面的内存空出来了,而且还不能用了,因为我们不能把元素从队头插进去。于是乎,聪明的人们想到了循环队列这种东西。当队尾插不进去,队头前面又还有空位的时候,就把队尾下调到队头前面的位置,但记住他还是队尾,如此下去,就不会担心内存的浪费了。下面用图来解释一下:

首次适应算法实验报告

操作操作系统大作业题目:首次适应算法分配内存 学号: 1207300142 学生姓名:张鲁云 班级:计科121

首次适应算法分配内存 一、问题描述 在内存分配中,动态分区是根据实际的进程需求,动态地为之分配空间。而首次适应算法分配时从表头指针开始查找可利用空间表,将找到的第一个大小不小于“请求”的空闲块的一部分分配给用户。可利用空间表本身既不按节点的初始地址有序,也不按节点的大小有序。用户释放内存,回收时只是将空闲块插入在链表的表头即可,此算法比较节省时间。 二、运行环境 VC6.0 三、算法思想。 首次适应算法要求空闲分区链以地址递增的次序链接。在分配内存时,从链首开始查找,直到找到一个大小能满足要求的空闲分区为止;然后按照作业大小,从该分区中划出一块内存空间分配给请求者,余下的空闲区仍留在空闲链中。若从链首到链尾都不能找到一个能满足要求的分区,则此次分配失败。 四、实验目的 在计算机系统中,为了提高内存区的利用率,必须给电脑内存区进行合理的分配。本实验通过对内存区分配方法首次适应算法的使用,来了解内存分配的模式。 五、首次适应算法分配内存算法概要 (1)结构体 Typedef struct freearea//定义一个空闲区说明表结构 { long size; //分区大小 long address; //分区地址 int state; //状态 }ElemType; // 线性表的双向链表存储结构 Typedef struct DuLNode { ElemType data; structDuLNode *prior; //前趋指针 structDuLNode *next; //后继指针 } DuLNode,*DuLinkList; Status Initblock(intMAX_length)//开创带头结点的内存空间链表 { block_first=(DuLinkList)malloc(sizeof(DuLNode)); block_last=(DuLinkList)malloc(sizeof(DuLNode)); block_first->prior=NULL; //头结点的前驱指针指向空 block_first->next=block_last; //头结点的后继指针指向尾结点 block_last->prior=block_first; //尾结点的前驱指针指向头结点 block_last->next=NULL; //尾结点的后继指针指向空 block_last->data.address=0; //尾结点的地址是0

操作系统复习题

1.操作系统是一种() A.应用软件 B.系统软件 C.通用软件 D.工具软件 2.计算机系统中,最外层的是() A.硬件系统 B.系统软件 C.支撑软件 D.应用软件 3.在作业调度算法中,若所有作业同时到达,则平时等待时间最短的算法是() A.先来先服务 B.优先级 C.响应比最高优先 D.计算时间短的作业优先 4.即考虑作业等待时间,又考虑作业执行时间的调度算法是() A.先来先服务 B.优先级 C.响应比最高优先 D.均衡 5.进程从执行到阻塞状态可能是由于()

A.请求某种资源 B.现运行进程时间用完 C.释放某种资源 D.进程调度程序的调度 6.在进程管理中,当()时.进程从阻塞状态变为就绪状态 A.进程被调度程序选中 B.等待某一事件 C.等待的事件发生 D.时间片用完 7.分配给进程占用处理机的时间用完或有更高优先级的另一进程要进入,迫使正在运行的进程让出处理机,则该进程状态变化的情况是() A.执行态—就绪态 B.执行态—阻塞态 C.就绪态—执行态 D.阻塞态—就绪态 8.时间片轮转调度算法经常用于() A.单用户操作系统 B.实时系统 C.分时操作系统 D.批处理系统 9.进程调度的关键是()

A.时间片的大小 B.进程调度算法 C.CPU速度 D.内存空间利用率 10.一次中断后可能引起若干个程序状态的变化,因此中断处理后,由()来决定哪个进程可占用处理机. A.进程调度 B.页面调度 C.移臂调度 D.作业调度 11.采用时间片轮调度算法是为了 A.多个终端用户得到系统的及时响应 B.先来先服务 C.需CPU最短的进程先来执行 D.优先级最高的进程能得到及时的调度 12.多道程序环境下,操作系统分配资源以()为基本单位 A.程序 B.指令 C.作业 D.进程

相关文档
最新文档