磁盘调度算法
要求模拟先来先服务法(First-Come, First-Served,FCFS),最短寻道时间优先法(Shortest Seek Time First, SSTF),电梯法三种磁盘调度算法,输入为一组请求访问磁道序列,输出为每种调度算法的磁头移动轨迹和移动的总磁道数。
实验代码:
/*
1、FCFS
2、SSTF
3、SCAN
测试队列(课本P202):98、183、37、122、14、124、65、67
*/
#include <iostream>
using namespace std;
typedef struct Node
{
int value; /*数据域*/
Node *next; /*指针域*/
}LinkNode,*LinkList;
void Show(LinkList Queue)
{
LinkNode *p = Queue;
while (p)
{
cout << p->value << ' ';
p = p->next;
}
cout << endl;
}
void CopyQueue(LinkList Queue, LinkList &QueueCopy)
{
LinkList q1, q2, p; int i = 0; //q是CopyQueue的活动指针
QueueCopy =new LinkNode; //创建链表副本的第一个结点
QueueCopy->next = NULL;
q1 = q2 = QueueCopy;
p = Queue;
while (p)
{
q2->value = p->value;
i++;
//cout << "拷贝第" << i << "个结点的值" << q2->value << endl;
if (p->next)
{
q2 = new LinkNode;
q2->next = q1->next;
q1->next = q2;
q1 = q1->next;
}
p = p->next;
}
q2->next = NULL;
}
void swap(int &a,int &b) /*交换函数*/
{
int temp;
temp = a;
a = b;
b = temp;
}
void HeadInsert(LinkList &QueueHead,LinkList InsertQueue) /*用头插法将Queue结点插入QueueTemp,使得原队列逆序*/
{
LinkNode *p = InsertQueue;
while (p)
{
LinkNode *QueueNode = new LinkNode;
QueueNode->value = p->value;
//cout << "已插入:" << p->value << endl;
QueueNode->next = QueueHead->next;
QueueHead->next = QueueNode;
p = p->next;
}
//cout << "头插测试:" <<endl;
//Show(QueueHead);
}
void HeadInsert(LinkList &QueueHead, LinkList InsertQueue,LinkNode *len) /*用头插法将Queue结点插入QueueTemp,使得原队列逆序*/
{
LinkNode *p = InsertQueue;
while (p!=len->next)
{
LinkNode *QueueNode = new LinkNode;
QueueNode->value = p->value;
//cout << "已插入:" << p->value << endl;
QueueNode->next = QueueHead->next;
QueueHead->next = QueueNode;
p = p->next;
}
//cout << "头插测试:" <<endl;
//Show(QueueHead);
}
void QueueSort(LinkList &Queue)
{//采用冒泡排序
LinkNode *p = Queue; int count = 0;
while (p->next != NULL)
{
count++;
p = p->next;
}
//cout << "计算排序趟数:" <<count<< endl;
for (int i = 0; i < count;i++)
{
p = Queue;
//cout <<"第"<<i<<"趟排序:"<< endl;
for (int j = 0; j < count - i;j++)
{
// cout << "第" << j <<"次交换"<< endl;
if (p->value > p->next->value)
swap(p->value, p->next->value);
//Show(Queue);
p = p->next;
}
//cout << endl;
}
//cout << "\n验证QueueSort:" << endl;
//Show(Queue);
//cout << endl;
}
void CreateQueue(LinkList &Queue)
{
int QueueLength; /*队列长度*/
LinkNode *QueueHead,*QueueNode1,*QueueNode2;
QueueHead = QueueNode1 = QueueNode2 = NULL;
cout << "请输入所要访问磁道队列的长度:";
cin >> QueueLength;
cout << "请输入所要访问磁道队列:";
for (int i = 0; i < QueueLength; i++) /*采用尾插法插入*/
{
if (i == 0)
{
QueueHead = new LinkNode;
cin >> QueueHead->value; /*输入头结点*/
QueueHead->next = NULL;
QueueNode1 = QueueNode2 = QueueHead;
}
else
{
QueueNode2 = new LinkNode;
cin >> QueueNode2->value; /*输入其它结点*/
QueueNode2->next = QueueNode1->next;
QueueNode1->next = QueueNode2;
QueueNode1 = QueueNode2;
}
}
QueueNode2->next = NULL;
Queue = QueueHead;
}
int MoveSum(LinkList Queue)
{
LinkNode *p = Queue; int count = 0,sum=0;
while (p->next != NULL)
{
count++;
p = p->next;
}
p = Queue;
for (int i = 0; i < count; i++)
{
// cout << "第" << i <<"次求和"<< endl;
sum += ((p->value) > (p->next->value) ? ((p->value) - (p->next->value)) : ((p->next->value) - (p->value)));
p = p->next;
}
return sum;
}
void FCFS(LinkList Queue,int start)
{
cout << "\nFCFS磁头移动轨迹:" << endl;
LinkList QueueCopy, QueueTemp;
CopyQueue(Queue, QueueCopy);
QueueTemp = new LinkNode;
QueueTemp->value = start;
QueueTemp->next = QueueCopy;
Show(QueueTemp);
cout << "移动磁道数:" ;
cout << MoveSum(QueueTemp) << endl;
}
void SSTF(LinkList Queue, int start)
{
cout << "\nSSTF磁头移动轨迹:" << endl;
LinkList QueueCopy, QueueTemp; /*QueueCopy队列副本,QueueTemp临时队列,QueueNode队列结点*/
LinkNode *first,*tail,*p, *QueueNode; /*first为第一个结点的指针,tail为尾结点指针,p为工作指针*/
p = first = tail = NULL;
CopyQueue(Queue, QueueCopy);
//cout << "显示Copy队列:" ;
//Show(QueueCopy);
QueueSort(QueueCopy);
//cout << "显示排序后的Copy队列:";
//Show(QueueCopy);
for (p= QueueCopy; p->next; p = p->next);
tail = p;
first = QueueCopy;
QueueNode = new LinkNode;
QueueNode->value = start;
QueueNode->next = NULL;
QueueTemp = QueueNode;
if (first->value >= start) /*将开始磁道号加入队列的首部*/
{
QueueTemp->next = QueueCopy;
Show(QueueTemp);
cout << "移动磁道数:";
cout << MoveSum(QueueTemp) << endl ;
}
else if (tail->value <= start) /*,将原队列逆序,并将开始磁道号加入新队列的首部*/
{
HeadInsert(QueueTemp, QueueCopy);
Show(QueueTemp);
cout << "移动磁道数:";
cout << MoveSum(QueueTemp) << endl;
}
else
{
int delta1, delta2; /*记录两个数的绝对值*/
LinkNode *left, *right, *pre; /*left和right是开始磁道号的左右结点位置,pre是left结点的前一个结点指针*/
left = first; /*左指针初始化为链表的首结点 */
right = left->next;
pre = NULL;
//创建访问的队列
//QueueTemp=new LinkNode; /*记录访问列表的第一个值*/
//LinkNode *pt= QueueTemp;
//QueueTemp->value = start;
//QueueTemp->next = NULL;
p = QueueTemp;
while (left&&right)
{
//first = QueueCopy;
left = first; /*左指针初始化为链表的首结点 */
right = left->next;
pre = NULL;
while (right->value < start)
{//右指针的结点值小于开始磁道号,左右指针右移
pre = left; //4 5 6 7 8 6
left = left->next;
right = left->next;
}
//cout << "上一个磁道号:" << start << endl;
delta1 = (((left->value)>start) ? left->value - start : start - left->value);
//cout << "左结点的值:" << left->value << endl;
delta2 = (((right->value)>start) ? right->value - start : start - right->value);
//cout << "右结点的值:" << right->value << endl;
//cout << "开始磁道号与左结点的差值:" << delta1 << endl;
//cout << "开始磁道号与右结点的差值:" << delta2 << endl<<endl<<endl;
if (delta1 < delta2)
{
start = left->value;
//将要访问的结点加入访问队列
QueueNode = new LinkNode;
QueueNode->value = start;
QueueNode->next = p->next;
p->next = QueueNode;
p = p->next;
if (pre)
{
pre->next = right;
}
else
{
QueueCopy = QueueCopy->next;
left = pre;
} /*删除已访问的结点*/
//cout << "第四个结点值测试:" << QueueTemp->next->next->next->value << endl;
delete left;
left = pre;
}
else
{
start = right->value;
//将要访问的结点加入访问队列
QueueNode = new LinkNode;
QueueNode->value = start;
QueueNode->next = p->next;
p->next = QueueNode;
p = p->next;
left->next = right->next; /*删除已访问的结点*/
//cout << "第二个结点值测试:" << QueueTemp->next->value << endl;
delete right;
right = left->next;
}
// pt = pt->next;
}
for (p = QueueTemp; p->next; p = p->next);
tail = p;
if (right) /*左指针移到空指针的位置*/
tail->next = QueueCopy;
else
HeadInsert(tail,QueueCopy);
Show(QueueTemp);
cout << "移动磁道数:";
cout << MoveSum(QueueTemp) << endl;
}
}
void SCAN(LinkList Queue, int start)
{
cout << "\nSCAN磁头移动轨迹:" << endl;
int status;
cout << " ---------------------温馨提示------------------" << endl;
cout << "+ 请选择电梯法的模式: +" << endl;
cout << "+ 1.先↓后↑ +" << endl;
cout << "+ 2.先↑后↓ +" << endl;
cout << " -----------------------------------------------" << endl;
cout << "选择模式:";
cin >> status;
if ((status!=1)&&(status!=2))
{
int i = 1;
cout << "无效的输入,请重试!"<<endl<<endl;
for (i = 1; i <= 3; i++)
{
cout << "选择模式:";
cin >> status;
if (status == 1 || status == 2)
break;
cout << "无效的输入,请重试!" << endl << endl;
}
if (i == 4)
{
cout << "输入错误次数过多,请重新运行程序!" << endl << endl;
return;
}
}
LinkList QueueCopy, QueueTemp; /*QueueCopy队列副本,QueueTemp临时队列,QueueNode队列结点*/
LinkNode *first, *tail, *p, *QueueNode; /*first为第一个结点的指针,tail为尾结点指针,p为工作指针*/
p = first = tail = NULL;
CopyQueue(Queue, QueueCopy);
//cout << "显示Copy队列:" ;
//Show(QueueCopy);
QueueSort(QueueCopy);
//cout << "显示排序后的Copy队列:";
//Show(QueueCopy);
for (p = QueueCopy; p->next; p = p->next);
tail = p;
first = QueueCopy;
QueueNode = new LinkNode;
QueueNode->value = start;
QueueNode->next = NULL;
QueueTemp = QueueNode;
switch (status)
{
case 1:
{
if (first->value >= start) /*将开始磁道号加入队列的首部*/
{
;
QueueTemp->next = QueueCopy;
Show(QueueTemp);
cout << "移动磁道数:";
cout << MoveSum(QueueTemp) << endl;
}
else if (tail->value <= start) /*,将原队列逆序,并将开始磁道号加入新队列的首部*/
{
HeadInsert(QueueTemp, QueueCopy);
Show(QueueTemp);
cout << "移动磁道数:";
cout << MoveSum(QueueTemp) << endl;
}
else
{
LinkNode *cre=first,*pre=NULL; /*当前工作指针*/
while (cre->value < start)
{
pre = cre;
cre = cre->next;
}
if (pre&&cre->value>start)
HeadInsert(QueueTemp, QueueCopy, pre);
else if(cre->value==start)
HeadInsert(QueueTemp, QueueCopy, cre);
for (p = QueueTemp; p->next; p = p->next);
tail = p;
tail->next = cre->next;
Show(QueueTemp);
cout << "移动磁道数:";
cout << MoveSum(QueueTemp) << endl;
}
}; break;
case 2:
{
if (first->value >= start) /*将开始磁道号加入队列的首部*/
{
;
QueueTemp->next = QueueCopy;
Show(QueueTemp);
cout << "移动磁道数:";
cout << MoveSum(QueueTemp) << endl;
}
else if (tail->value <= start) /*,将原队列逆序,并将开始磁道号加入新队列的首部*/
{
HeadInsert(QueueTemp, QueueCopy);
Show(QueueTemp);
cout << "移动磁道数:";
cout << MoveSum(QueueTemp) << endl;
}
else
{
LinkNode *cre = first,*pre=NULL; /*当前工作指针*/
while (cre->value < start)
{
pre = cre;
cre = cre->next;
}
QueueTemp->next = cre;
for (p = QueueTemp; p->next; p = p->next);
tail = p;
if(pre)
HeadInsert(tail, QueueCopy, pre);
Show(QueueTemp);
cout << "移动磁道数:";
cout << MoveSum(QueueTemp) << endl;
}
}; break;
default:
break;
}
}
int main()
{
int status;
cout << " ----------------实验八 磁盘调度算法------------" << endl;
cout << "+ 请选择磁盘调度算法: +" << endl;
cout << "+ 1.FCFS +" << endl;
cout << "+ 2.SSTF +" << endl;
cout << "+ 3.SCAN +" << endl;
cout << " -----------------------------------------------" << endl;
cout << "选择算法(序号):";
cin >> status;
if ((status != 1) && (status != 2)&&(status != 3))
{
int i = 1;
cout << "无效的输入,请重试!" << endl << endl;
for (i = 1; i <= 3; i++)
{
cout << "选择算法(序号):";
cin >> status;
if (status == 1 || status == 2||status==3)
break;
cout << "无效的输入,请重试!" << endl << endl;
}
if (i == 4)
{
cout << "输入错误次数过多,请重新运行程序!" << endl << endl;
return 0;
}
}
int start; /*开始的磁道号*/
LinkList Queue;
CreateQueue(Queue); /*创建要访问的磁盘服务队列*/
cout << "请输入初始磁道号:";
cin >> start;
switch (status)
{
case 1:
FCFS(Queue, start); break;
case 2:
SSTF(Queue, start); break;
case 3:
SCAN(Queue, start); break;
default:
break;
}
cout << endl;
cout << " -----------------------------------------------" << endl;
cout << "+ 姓名: XXX +" << endl;
cout << "+ 学号: XXXXXXXXX +" << endl;
cout << "+ 班级: XXXXXX +" << endl;
cout << "+ 指导老师: XXXX +" << endl;
cout << " -----------------------------------------------" << endl;
return 0;
}
运行结果:
1、FCFS
2、SSTF
3、SCAN
(1)先下后上
(2)先上后下