zoukankan      html  css  js  c++  java
  • 哨兵/sentinel:在算法设计中的应用

    哨兵(sentinel)
    昨天看算法导论里对哨兵的描述后,觉得这是一种很有意思的编程思想。
    哨兵是一个哑对象。一般哨兵不存放任何数据,但其结构体与其他有用的元素一致。
    正如其字面意思,哨兵是在边界保卫祖国的军人,所以在编程的世界里,哨兵充当着简化边界条件处理的角色。

    比较常见的应用是直接插入排序里的哨兵。
    在直接插入排序里使用数组首位A[0]作为哨兵,这里的哨兵有两个作用:
    1、暂时存放待插入的元素和防止数组下标越界。
    2、简化了判断上的表达:循环头部的控制条件应为j>0与A[j]>t转化成比较一次:A[j]>A[0]

    再比如算法导论里介绍的一个加上了哨兵的双向循环链表(书p238)。
    在这个数据结构里,为了简化对边界条件的判断与维护,单独地生成一个结构对象与其他链表结点一致的结点,prev域指向表尾,next域指向表头。
    正因为next域指向表头,在对链表处理的过程中可以省去头指针,直接用对哨兵的引用来代替对头指针的引用。
    如图所示:(图自算法导论P238)

    又比如扫雷游戏,每次点击一个格子就要扫描相邻的8个格子。当点击到边界的时候,相邻不足8个格子,这时候就可以在设计游戏的时候为边界外圈加上隐藏的一层格子。这样就可以使所有的操作一致化,不需要对边界的条件作出特殊的处理。

    总结:
    1、哨兵基本不能降低数据结构相关操作的渐近时间界,但其可以降低常数因子。
    2、哨兵的设计可以使得代码更简洁,可以省去一些由于边界环境不同而作出的特殊处理。
    3、在某些情况下哨兵可以使得循环语句更紧凑,降低运行时间里n或者n²项的系数。
    4、慎用:哨兵会占用额外的内存。当使用哨兵的开销较大时,有可能会造成严重的浪费。

  • 相关阅读:
    c# 服务
    c#调用腾讯云API的实例
    c#的WebService和调用
    基于H5的WebSocket简单实例
    Windows server 2008 R2配置多个远程连接
    把本地项目上传到git服务器的步骤
    swagger-ui中@ApiOperation实例
    VUE学习系列--(一)
    IntelliJ IDEA自动添加类注释和方法注释
    Jeecg-Cloud学习之路(二)
  • 原文地址:https://www.cnblogs.com/AKsnoopy/p/8601726.html
Copyright © 2011-2022 走看看