编程之美---电梯调度算法

在看linux 0.11版本的块设备驱动部分,里面提到了电梯算法,总结下几种寻道的方式。

        第一种:最为原始的先到先服务(first come first served)的算法。假设此时我们正在第11道读取数据,然后陆陆续续有其他进程来要求我们提供磁盘内容给他们。这里我们把要读取的柱面按照进程提出要求的顺序记录下来,比如1, 36, 16, 34, 9, 12,那么严格按照先到先服务原则,我们下一个要去的柱面是1号,中间要经历10个柱面,然后是36号....... 等全部读下来,我们统计下,一共要"跑过"111个柱面,这个算法效率太低。
        第二种是最短寻道算法(shortest seek first) 这种算法有点类似贪心,即是每次我们选择距离我们现在所处的点最近的一个点(柱面)。如下图,若当前我们正好执行完对于11号块的读取,下一个最近的是12号块,那么我们读取12号块的数据,接着读取16号块...... 我们看到如果用这种算法的话,我们经过的方块号码 12, 9, 16, 1, 34, 36 这样我们总共的经历的柱面数为 61块,这样我们大大节省了寻道时间。 这个算法本来已经很好了,不过我们不得不面临这样一个问题: 现在我们正在读取16号块,马上要读取1号块了,这是一个进程闯进来要求我们为他提供20号块的信息,20号距离16号比较近,那我们就去二十号吧,然后我们又接到通知要23号数据.....假如一直有更接近的请求过来那1号很可能需要很久才能读取它内容!所以这里我们需要一种算法来平衡效率和公平性,避免上述过程中的饥饿,所以我们引进了电梯算法。
        第三种电梯算法:我们需要做一个标记,标记现在是向数字大的方向读,还是方向小的。如果现在是向前(数字大)读,那么我们就需要一直读下去,一直到最尾一个。同理向后读。这个算法如下图所示: 一种平衡效率和公平性的算法(不要让饿死)
        总结:①先到先服务:保证了公平性,但效率低;②最短寻道算法:效率高,但不能保证公平性(有可能饿死)③电梯算法:平衡了效率和公平性
--------------------- 
出处:https://blog.csdn.net/heiworld/article/details/27978521 
 

编程之美-电梯调度算法
   大部分参考文章http://www.cppblog.com/jake1036/archive/2011/06/29/149720.html(将它的c语言改写成了java版)
  一问题描述:
     所有的员工均在1楼进电梯的时候,选择所要到达的楼层。
     然后计算出停靠的楼层i,当到达楼层i的时候,电梯停止。
     所有人走出电梯,步行到所在的楼层中。
     求所有人爬的楼层数目和的最小值。 
 
二 问题解决方法:
   解决方案:
  (1)使用简单的方法,直接将楼层从1到n开始遍历
       sum(person[i] *  |i - j| ) 此表达式为一个双重循环,i与j均为1-n的循环。 
       j下标表示电梯停靠的楼层。 
       person数组表示,对应i层的下电梯的人数。此算法负责度为o(n*n) 
       对应的j是上述和为最小的一层即为所求。 上面的算法复杂度为o(n) 
       
  (2)下面考虑一个简单的算法,使其复杂度达到o(n)
      考虑假如电梯停靠在某一楼层i处,假设在i处下楼的客人为N2,
      在i以上楼层的客人数目为N3 ,在i一下楼层的客人数目为N1。 
      且将电梯在i层停止时,全部人员的路程之和记为T。 
      
      那么加入电梯在i-1层停的话,则原来i层之上的人需要多爬一层,即增加了N3
      第i层的人需要多爬一层,则结果增加了N2,  i层之下的人则少爬了一层,结果减去N1
      所以第i-1层的结果为 T - N1 + N2 + N3 。即结果可以即为 T -(N1 - N2 - N3) 
      
      
      下面考虑在i+1层的结果,若电梯在i+1层停止的话,原来i层之上的客户都会少爬一层,
      则结果减少N3 ,而i层之下的人员则都会多爬一层即增加了N1 ,第i层的人员都会多爬一层
      即为增加了N2 。则结果为 T + N1 + N2 - N3 
        
      综上我们得出,
      (1)若N1 > N2 + N3的时候, 我们在第i-1层 选择电梯停止最好。
      (2)若N1 + N2 < N3的时候, 我们选择在第i+1层停止电梯最好。  
        
      下面我们可以先计算出来当i=1时候的T ,然后判断是否需要在i+1层停止,若是i+1层的花费
       大于i层,则我们可以继续计算,否则退出。

  三 代码如下:

public class DianTi 
{
    static final int N = 10 ;
    static int person[] = {0, 2, 5 , 7 , 3 , 5 , 2 , 6, 2 , 6 , 3}; 
    public static void main(String[] args)
    {
        System.out.print(compute(person)+" "+compute2(person));
    }
    public static int compute(int[] person)
    {
          //先计算出在第一层停止的时候 所需要的花费
           int T = 0;
           int N1 = 0 ; //在第一层以下下的人数 
           int N2 = person[1] ; //在第一层处下的人数 
           int N3 = 0 ;      //在第一层之上下电梯的人数 
           int floor =  1 ;
           for(int i = 2 ; i <= N ;i++) //先计算出第1层停止需要爬取的楼层数目 
           {
             T  += person[i] * (i - 1) ;
             N3 += person[i] ;     
           }
            
           for(int i = 2 ; i <= N ;i++)
           {
             if(N1 + N2 <= N3) //说明第i+1层的结果会大于第i层 
               {
                   T += N1 + N2 - N3 ;
                   N1 += N2 ;
                   N2 = person[i] ; 
                   N3 -= person[i] ;
                   floor = i ;
                   
               }     
               else  //否则第i层的结果已经最小,故不需要计算第i+1层 
               break ; 
                
           }     
           return floor ;
    }
    public static int compute2(int[] person)
    {
              int tempfloor = 0 ;
              int min = 6553 ;//存储最小值
              int floor = 1   ;//存储停靠的楼层 
              int j;
              for(int i = 1 ; i <= N ;i++) //表示第i楼层电梯停靠 
              {
                tempfloor = 0 ;         
                for(j = 1 ; j < N ;j++)      
                    tempfloor += Math.abs((i - j)) * person[j] ;         
                if(min > tempfloor)   
                {
                  min = tempfloor ;
                  floor = i ;          
                }                                       
              }
              return floor ;      
    }
}


结果如下:
5 5


出处:https://blog.csdn.net/Jarvan_Song/article/details/52304363

猜你喜欢

转载自blog.csdn.net/JackLiu16/article/details/83212830