❶ A*算法 和 最佳优先搜索算法(Best-First-Search)
最佳优先搜索算法是一种启发式搜索算法(Heuristic Algorithm),其基于广度优先搜索算法,不同点是其依赖于估价函数对将要遍历的节点进行估价,选择代价小的节点进行遍历,直到找到目标点为止。 BFS算法不能保证找到的路径是一条最短路径,但是其计算过程相对于Dijkstra
算法会快很多 。
最佳优先搜索是一种启发式搜索算法。广度优先搜索和深度优先搜索都属于穷举类型的搜索,需要依次遍历所有的节点,当空间非常大的时候,这种方式的效率就会非常差。而启发式的搜索是对状态控件中的每个点进行评估,然后选出最好的位置。
启发估价函数公式为:
n表示当前的点,g(n)为从起始点到点n的实际代价,h(n)为从点n到目标点的估价。
(图片来源于网络)
A*算法将BFS算法和Dijkstra算法结合在一起,结合两算法的优点,既可以查找最短路径的,有拥有和BFS差不多的效率。
(图片来源于网络)
A*算法详解
模拟寻路的地址
❷ 动态高优先权优先调度算法
动态高优先权优先调度算法:
动态优先权是指,在创建进程时所赋予的优先权,是可以随进程的推进或随其等待时间的增加而改变的,以便获得更好的调度性能。例如,我们可以规定,在就绪队列中的进程,随其等待时间的增长,其优先权以速率a提高。若所有的进程都具有相同的优先权初值,则显然是最先进入就绪队列的进程,将因其动态优先权变得最高而优先获得处理机,此即FCFS算法。若所有的就绪进程具有各不相同的优先权初值,那么,对于优先权初值低的进程,在等待了足够的时间后,其优先权便可能升为最高,从而可以获得处理机。当采用抢占式优先权调度算法时,如果再规定当前进程的优先权以速率b下降,则可防止一个长作业长期地垄断处理机。
算法代码模拟实现:
#include<stdio.h>
#include<stdlib.h>
#defineN6
//待插入就绪队列的进程数据
intid[N]={0,1,
2,3,4,
5};
intpriority[N]={9,38,17,
2,7,18};
intcpuTime[N]={0,
0,0,0,
0,0};
intallTime[N]={3,
2,3,6,
1,3};
//********************************
//
//模拟进程/PCB数据结构
//
//********************************
//
枚举进程的状态:就绪、执行、阻塞、完成
enumSTATE{Ready,Run,Block,Finish
};
//建立PCB结构体
structPCB{
intid;//标志数
intpriority;//优先数
intcpuTime;//
已占CPU时间
intallTime;//
还需占CPU时间
intblockTime;//已被阻塞的时间
STATEstate;//
进程状态
PCB*pre;//
PCB的前指针
PCB*nxt;//
PCB的后指针
};
//********************************
//
//模拟进程队列
//
//********************************
//进程入列
voidqueQush(PCB*process,PCB
*queHead)
{
process->pre=NULL;
process->nxt=
queHead->nxt;
if(queHead->nxt!=NULL){
//非第一个入列
queHead->nxt->pre=
process;
}
queHead->nxt=process;
}
//进程出列
voidquePop(PCB*process,PCB
*queHead)
{
if(process->pre!=NULL){
//不是头节点
process->pre->nxt=
process->nxt;
}
else{
queHead->nxt=
process->nxt;
}
if(process->nxt!=NULL){
//不是尾节点
process->nxt->pre=
process->pre;
}
//
清空进程指针
process->pre=process->nxt=
NULL;
}
//查看队列里进程的信息
voidqueWalk(PCB*queHead)
{
PCB*pro=queHead->nxt;
if(pro==NULL){
printf("(无进程) ");
return;
}
while(pro!=NULL)
{
printf("id:%d,
pri:%d,alltime:%d ",
pro->id,
pro->priority,
pro->allTime);
pro=
pro->nxt;
}
}
//********************************
//
//模拟就绪队列
//
//********************************
intreadyQueNum;//就绪队列的进程数量
PCBreadyQueHead;//
就绪队列的头部
PCB*readyMaxProcess;//就绪队列中优先级最高的进程
//进程插入到就绪队列
voidreadyQueQush(PCB
*process)
{
readyQueNum++;
process->state=Ready;
queQush(process,&readyQueHead);
}
//优先级最高的进程出列
PCB*readyQuePop()
{
readyQueNum--;
quePop(readyMaxProcess,
&readyQueHead);
returnreadyMaxProcess;
}
//每个时间片,更新就绪队列里进程的信息
voidreadyQueUpdate()
{
intmaxPriority=-1;
PCB*pro=readyQueHead.nxt;
if(pro==NULL){
//就绪队列没有进程
readyMaxProcess=
NULL;
return;
}
while(pro!=NULL)
{
pro->priority
++;
if(pro->priority>maxPriority)
{
maxPriority=
pro->priority;
readyMaxProcess=pro;
}
pro=
pro->nxt;
}
}
//返回就绪队列最高优先级的值
intreadyMaxPriority()
{
returnreadyMaxProcess->priority;
}
//查看就绪队列里进程的信息
voidreadyQueWalk()
{
printf("就绪队列里的进程信息为: ");
queWalk(&readyQueHead);
}
//********************************
//
//模拟阻塞队列
//
//********************************
#defineEndBlockTime3
//进程最长被阻塞时间
intblockQueNum;//阻塞队列的进程数量
PCBblockQueHead;//
阻塞队列的头部
PCB*blockMaxProcess;//阻塞队列中优先级最高的进程
//进程插入到阻塞队列
voidblockQueQush(PCB
*process)
{
blockQueNum++;
process->blockTime=0;
process->state=Block;
queQush(process,&blockQueHead);
}
//优先级最高的进程出列
PCB*blockQuePop()
{
blockQueNum--;
quePop(blockMaxProcess,
&blockQueHead);
returnblockMaxProcess;
}
//每个时间片,更新阻塞队列里进程的信息
voidblockQueUpdate()
{
intmaxPriority=-1;
PCB*pro=blockQueHead.nxt;
while(pro!=NULL)
{
pro->blockTime
++;
if(pro->blockTime>=EndBlockTime)
{
PCB*process=pro;
pro=pro->nxt;
//阻塞时间到,调入就绪队列
blockQueNum--;
quePop(process,
&blockQueHead);
readyQueQush(process);
}else
if(pro->priority>maxPriority)
{
//更新阻塞队列里优先级最高的进程指针
maxPriority=
pro->priority;
blockMaxProcess=pro;
pro=pro->nxt;
}
}
}
//查看阻塞队列里进程的信息
voidblockQueWalk()
{
printf("阻塞队列里的进程信息为: ");
queWalk(&blockQueHead);
}
//********************************
//
//模拟动态优先权的进程调度
//
//********************************
//初始化数据
voidinitData()
{
//
初始化就绪队列和阻塞队列
readyQueNum=blockQueNum=0;
readyMaxProcess=blockMaxProcess=NULL;
readyQueHead.pre=readyQueHead.nxt=NULL;
blockQueHead.pre=blockQueHead.nxt=NULL;
//
初始化进程进入就绪队列
inti,maxPriority=-1;
for(i=0;i<N;i
++)
{
//分配一个PCB的内存空间
PCB*pro=(PCB
*)malloc(sizeof(PCB));
//给当前的PCB赋值
pro->id
=id[i];
pro->priority
=priority[i];
pro->cpuTime
=cpuTime[i];
pro->allTime
=allTime[i];
pro->blockTime
=0;
if(pro->allTime>0){
//插入到就绪队列中
readyQueQush(pro);
//更新就绪队列优先级最高的进程指针
if(pro->priority>
maxPriority){
maxPriority=pro->priority;
readyMaxProcess=pro;
}
}
}
}
//模拟cpu执行1个时间片的操作
voidcpuWord(PCB
*cpuProcess)
{
cpuProcess->priority-=3;
if(cpuProcess->priority<0)
{
cpuProcess->priority=0;
}
cpuProcess->cpuTime++;
cpuProcess->allTime--;
//
显示正执行进程的信息:
printf("CPU正执行的进程信息为: ");
printf("id:M,pri:M,
alltime:M ",
cpuProcess->id,
cpuProcess->priority,
cpuProcess->allTime);
}
intmain()
{
inttimeSlice=0;//
模拟时间片
intcpuBusy=0;
//模拟cpu状态
PCB*cpuProcess=NULL;//当前在cpu执行的进程
//
初始化数据
initData();
//
模拟进程调度
while(1)
{
if(readyQueNum==0
&&blockQueNum==0
&&cpuBusy==0){
//就绪队列、阻塞队列和cpu无进程,退出
break;
}
//printf(" %d%d",
readyQueNum,blockQueNum);
if(cpuBusy==0)
{
//cpu空闲,选择一个进程进入cpu
if(readyQueNum>0)
{
//
选择绪队列优先级最高的进程
cpuProcess
=readyQuePop();
}else{
//
就绪队列没有进程,改为选择阻塞队列优先级最高的进程
cpuProcess
=blockQuePop();
}
cpuProcess->cpuTime=
0;
cpuProcess->state=
Run;
cpuBusy=1;
}
timeSlice++;
printf(" 第%d个时间片后: ",
timeSlice);
//
模拟cpu执行1个时间片的操作
cpuWord(cpuProcess);
if(cpuProcess->allTime==0){
cpuProcess->state=
Finish;
//释放已完成进程的PCB
free(cpuProcess);
cpuBusy=0;
}
//
更新就绪队列和阻塞队列里的进程信息
blockQueUpdate();
readyQueUpdate();
//
查看就绪队列和阻塞队列的进程信息
readyQueWalk();
blockQueWalk();
if(cpuBusy==1
&&readyQueNum>0
&&
cpuProcess->priority
<readyMaxPriority()){
//需抢占cpu,当前执行的进程调入阻塞队列
blockQueQush(cpuProcess);
cpuProcess=readyQuePop();
}
}
printf(" 模拟进程调度算法结束 ");
return0;
}
❸ 优先级调度算法
优先级调度算法的原理是给每个进程赋予一个优先级,每次需要进程切换时,找一个优先级最高的进程进行调度。这样,如果赋予长进程一个高优先级,则该进程就不会再“饥饿”。事实上,STCF算法本身就是一种优先级调度,只不过它给予短进程高优先级而已。
优先级调度的优点是可以赋予重要的进程以高优先级以确保重要任务能够得到CPU时间。其缺点则与STCF算法一样,低优先级的进程可能会“饥饿”。不过,这个问题在优先级调度算法里比在STCF里好解决:只要动态地调节优先级即可。例如,在一个进程执行特定CPU时间后将其优先级降低一个级别,或者将处于等待进程的优先级提高一个级别。这样,一个进程如果等待时间很长,其优先级将因持续提升而超越其他进程的优先级,从而得到CPU时间。这样,“饥饿”现象就可以防止。
不过,优先级调度还有一个缺点,就是响应时间不能保证,除非将一个进程的优先级设置为最高。即使将优先级设置为最高,但如果每个人都将自己进程的优先级设为最高,则响应时间还是无法保证。