• 就绪表


    就绪表

    • 适用于理解ucosII任务优先级,以及资源管理分配等

    在开始阅读之前,我希望你能明白以下的一些基本的思想,对于理解后续的内容有一定的相关性。

    1. 对于非有即无的东西,为了尽量的节约空间占用,我们可以用1bit来表示信息。
    2. 对于程序中空间与时间的取舍,绝大部分情况下灰采用空间换取时间,毕竟时间就是金钱。

    ucos-II之任务优先级

    在ucos-II中,支持64个优先级,那么怎么查找最高优先级,以及优先级的设置,清除等,抛开书中讲的,你会怎么实现?

    方法一:

    bool Priodata[64] = {0},具体如何做,这个就是通过for循环来查表了,从Priodata[0]元素查询到[63],查到该元素的数字为1为止。

    方法二:
    • 既然都是bool型的,为什么不能用1bit来表示?何必浪费7倍的bit来表示?

    所以有了如下:

    /* 8*8的bit数 */
    PrioTable[8] = {0};
    

    以下是图:

    思路:伪代码,应该都会看的懂(没有做其他的一些处理。)

      for i in 0 to 8:
        if PrioTable[i] != 0:
          for j in 0 to 8:
            if (PrioTable[i] & (1 << j)) == 1:
              return i*8 + j
    

    很多时候,如果能写出以上的代码,是对空间的利用更好的一点,但是,还是要经过循环(有的时候会嵌套)来达到查询的目的,是否有一种方法能有效的减少查询的次数呢?所以,这里引进一个数据,专门用来存储表示一些信息。

    方法三:
    • 数据的压缩,来表示整体,即增加限定词。

    PS:不得不说,现实世界中处处存在这样的情况。如果要在某个小区找某一户,首先,我们会限定在那一栋,哪一个单元,哪一个楼层等等。

    在这里,增加一组数据表示PrioTable[8]中当前某一个数据是否存在数据。本着节约资源的原则,我们定义一个数据:

    uint8 GrpData = 0;
    以下是图:

    为了方便强迫症患者,把它旋转为主流的样子:

    这个东西来表示什么的呢?就是用来表示PrioTable[i]中第i个元素是否有值存在.

    所以,查找最高优先级这种游戏就变成了:

    1. 查找GrpData数据中从bit0-bit7中最低为1的位
    2. 查找对应的PrioTable[i]中从bit0-bit7中最低为1的位.

    PS:理解了以上这两句话的可以不用看下面的。

    既然都是查找uint8中的最低为1的位,有几种方法:

    1. 循环查找
    2. 查表查找

    前面一种就不用说了,说后面这种,最简单的办法就是,将uint8所能表示的数字来一个全遍历,存起来,直接索引!
    所以,对于有:

    1. 0000,0000没找到,为0
    2. 0000,0001为bit0,为0
    3. 0000,0010为bit1,为1.
    4. 0000,0011为bit0,为0
    5. 0000,0100为bit2,为2

    依次类推,这个可以通过程序生成,附带优先级查找表:

    那么找到了GrpData最低位x,与PrioTable[x]中最低位y(注意其中的x),有几种方法可以得到当前的优先级:

    1. x表示第几组.
    2. y表示第几列.

    所以 x*8 + y,如果是不喜欢用乘法的童鞋,肯定会将以上的乘法修改为x<<3 + y
    到此,大体可以结束了的,有兴趣可以看看下面。

    数的组合与位信息表示

    很多解释上面那个x<<3的时候,解释的不是很清楚,我说说自己的理解。
    在计算机或者自然科学中,都存在有效位一说,特别是计算机中,涉及到LSB,MSB等。
    在对数据进行分组的时候,我们可以将数据进行拆分:

    以上图为例,我们将16个数据组成为一组,当满了16个数据以后,前进一位(溢出),用高位上的数据位来表示,是不是很像16进制?数据的组合其实也是这样子的。
    在就绪表中,我们将8个数据组合为1组,即通过一个uint8的后三位表示一组中的某个元素,以前面的高位来表示是第几组的数据。
    所以,如果后期不是64个优先级,需要扩展或者压缩,可以通过这种分组的方式进行思考,相应的把GrpData的数据进行扩展/缩减,当然扩展的话就不能用uint8来表示了,这个需要用到循环一次的方式来表示。大体方法类似。

    优先级的写入与清除

    对于位操作的写入与清除,有几个很有用的位操作运算。具体的可以看我以前写的关于怎么给某一位写1与写0(即清除).(PS:貌似没找到,大概说一下:)

    • 写1:
    • PrioTable[i] |= (1<<j)
    • 写0:
    • PrioTable[i] &= (~(1<<j))

    当然,还有其他的方法进行写和清除。
    那么,如何做到匹配以上的思想呢?那么再创建一个MaskTable.
    MaskTable[8] = {1,2,4,8,16,32,64,128};可以直接得到的最低位索引这个表格,然后将对应的位写入进去。

    资源管理表

    前面说到的是查找第一个为1的数即为第一个优先级。既然查找1都有,为什么没有查找0呢?什么时候去查找0,查找0的查找表又是什么样子的?
    在资源的使用上,经常会用类似的方式来标定那些资源已经被使用,那么没有被使用,如果没有被使用,肯定优先使用某一部分的资源(按照某一个可以遵循的规则)。

    比如说:优先使用前面的,那是不是需要查找第一个为0的数据?
    算法类似,只是256的表不同。
    0. 0000,0000bit0,为0

    1. 0000,0001bit1,为1
    2. 0000,0010bit0,为0.
    3. 0000,0011bit2,为2
    4. 0000,0100bit0,为0
      依次,也可通过程序生成,类似于这种图:
  • 相关阅读:
    [NOI2001]炮兵阵地 状压DP
    [GDOI2014]拯救莫莉斯 状压DP
    [ZJOI2010]数字计数 数位DP
    [APIO2007]动物园 状压DP
    [SDOI2013]淘金 数位DP
    环状最大两段子段和
    [清华集训2014]奇数国
    [HNOI2003]激光炸弹
    [SCOI2010]字符串
    [SCOI2005]扫雷
  • 原文地址:https://www.cnblogs.com/ply616/p/5713246.html
Copyright © 2020-2023  润新知