表驱动(直接访问、索引访问、阶梯访问)及别名算法(Alias Method)
表驱动(直接访问、索引访问、阶梯访问)
表驱动是一种编程模式(scheme),将复杂的逻辑从代码中独立出来,便于单独维护
直接访问表 Direct Access
- 通过索引值(下标)直接从表中找到对应的条目
案例
案例1:(一维查找:即可以代替一层的if结构或者switch结构):
比如你要查找1--12月份每个月的天数,如下:
month_day[12] = {31,30,29,30,30,31,31,31,30,30,31,30};
return month_day[5];
这样直接对应的就是5月的天数;
案例2:(三维查找:即有三个条件同时限制,如果使用if 或者 switch 可能需要三层嵌套结构)
比如一个路由景点,收费标准因 性别,是否学生,以及是否残疾 三项 共同决定门票的价格,那么,我们可以
使用三维数据驱动表来代替 复杂的上层if 语句;
int entrance_ticket_fee[][][] =
{{ {0,10} , {0,15} }, { {0,15},{15,30} } }
这是一个三维向量,三个维度分别代表了不同的限制,
第一维代表性别,索引 0代表女,1 代表男;
第二维代表是否是学生,索引 0代表是,索引 1 代表不是;
第三维代表是否是残疾, 索引 0代表残疾, 索引 1代表健康;
以上这个三维数组代表的是:
- 女孩,学生,残疾 0元
- 女孩 ,学生,健康 10元;
- 女孩, 非学生,残疾 0 元;
- 女孩, 非学生,非常急15元;
- 男孩,学生,残疾 0元;
- 男孩,学生,健康,15元;
- 男孩,非学生,残疾 15元;
- 男孩,非学生,健康,30元;
通过给定性别,是否是学生,是否残疾,来确定其返回值;
return entrance_ticket_fee[0][1][1]; //15元;
索引访问 Indexed Access
- 是一种间接访问技术
- 先用一个基本类型的数据从一张索引表中查出一个键值,然后再用这一键值查出你感兴趣的主数据
示例
假设你经营着一家商店,有大约100 种商品。再假设每种商品都 有一个4 位数字的物品编号, 其范围是0000 到9999
如果你想用这个编号作为键值直接查询一张描述商品信 息的表,那么就要生成一个具有10000 条记录的访问表
个人理解,其实就是一种减少冗余的方式
优点
- 如果主查询表中的每一条记录都很大,那么索引数组就 可以节省很多空间
- 操作位于索引 中的记录有时也要比操作位于主表中的记录更方便更廉 价
- 编写到表里面的数据比嵌入代码中的数据更容易维护
阶梯访问 Start-step Access
- 通过确定每项命中的阶梯层次确定其归类
案例
如果你正在开发一个等级评定的应用程序,按照如下等级区间 对分数定级
因为是浮点数,很难直接做出表,需要按照区间判断
所以,我们把每一区间的上限写入一张表里,然后写一个循环,按照各区间的上限来检查分数。当分数第一次超过某个区间的上限时,你就知道相应的等级了
注意:
- 端点
- 可以二分查找优化
随机数生成
需求:
- 生成符合某种概率分布的类型
解法一:阶梯访问
解设要生成的概率如下
可以将其累加,变成“阶梯”
生成0~1的随机数,判断落在哪个区间,就属于哪种类型
缺点:最多需要比较n次
解法二:别名算法
如果有n种类型,就将其乘n
此时会有概率大于1的和小于1的,接下来就是构造出某种算法用大于1的补足小于1的,使每种概率最后都为1,注意,这里要遵循一个限制:每列至多是两种概率的组合。
生成{1,2,3,4}
中的随机数A,0~1的随机数B
如果B>Prob{A}
,就选择Alias{A},否则选择A
reference
表驱动的认识以及用法——原创---非抄书_10891086的技术博客_51CTO博客