* 定时器的应用与原理:
游戏中。活动的状态、游戏数据的保存与载入、BOSS刷新时间等等,都可能会用到定时器。而堆对于定时器的实现有着至关关键的数据。
定时器的工作原理事实上不难,就是内部保存多个时间及其回调函数。当系统时间达到我们保存的时间值时,就运行回调函数。从而达到定时工作的效果。
同一时候,推断是否达到指定时间时。仅仅须要推断最早的时间(最早的时间没有达到,更晚的时间肯定不会达到),因此须要对时间列表进行排序。
起初,我设想定时器内部用于保存时间的数据结构是列表;理由是easy理解、实现简单。并且删除节点的时间复杂度为O(1)(对于定时器为说。删除超时时间,而超时时间肯定是在头结点。因此时间复杂度为O(1))。
可是这样的做法有明显的不足,由于保存时间列表须要排序。因此插入时间节点的时间复杂度为O(n)。
后来。发现堆在定时器有着很好的效率。可是堆排序的时间复杂度为O(nlog2n),“XXX,那不是比列表还慢!”。事实上不然,我们不须要将整个序列都排好序。前面我已经说过“推断是否达到指定时间时,仅仅须要推断最早的时间”。也就是说我们仅仅须要知道整个序列的最早时间就可以。
而堆排序刚好有这种一个名词“小顶堆”。也就是说每次插入时间节点和删除节点,都将序列维持在小顶堆的状态就可以。
对于小顶堆,插入节点。又一次调整堆结构。其时间复杂度为O(log2n);删除节点,又一次调整堆结构,其时间复杂也为O(log2n)。
因此整个用小顶堆实现的定时器的时间复杂也就是O(log2n)。
比起用列表(list)实现的时间复杂度O(n),效率大大提升。
* 小顶堆解说:
堆的保存结构是数组,而堆分为大顶堆和小顶堆,满足Key[i]>=Key[2i+1]&&key[i]>=key[2i+2]称为大顶堆,满足 Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]称为小顶堆。
也就是说。大顶堆的每个节点都比子节点大。小顶堆的每个节点都比子节点小。因此由上述性质可知大顶堆的堆顶的keyword肯定是全部keyword中最大的,小顶堆的堆顶的keyword是全部keyword中最小的。
堆是一棵全然二叉树。以下讲述小顶堆在构造。
插入节点:
首先在树的末端插入新结点,新结点与父结点假设新结点大于等于父结点。则不须要改变;否则交换位置。
删除堆顶:
删除堆顶跟删除节点的原理一样,而删除节点跟插入节点刚好相反,删除的节点向下查找两个子节点中最小的节点A替换自己的位置,节点A又相当于删除的节点继续向下查找。直到叶子节点。