提高效率,就要少做事情(三)

      在我们的日常生活中,常常会遇到这样的场景:手头上有N件事情等待做完,这时候呢突然新加进来了一件事情,事情总数量变成了N+1件,那么我们该把新加进来的事情放在什么位置等待处理呢?在很多时间管理相关的书籍中,都有一个明确的时间安排原则,叫“要事先行”,也就是说我们应当最优先去处理那些最重要、最紧急的事情。所以,从提高效率的角度来说,就需要将新加进来的事情按照紧急程度,插入到待处理事情的队列当中。

      那么,如何将新加进来的事情插入到待办事情的队列中呢?我们首先会想到之前学习的排序方法,即有了新元素之后,把现在队列中所有的元素进行一次排序,这样就插入元素之后的优先级顺序就排好了。但是,排序是一件非常耗费时间资源的事情,有没有更好的办法,让我们不排序,一旦有元素新进来的时候,就能够保证队列出口处的元素是优先级最高的,然后队列出列时,优先级最高的元素马上得到处理。

      解决这个问题,在计算机算法的研究上创建了一种数据结构,叫做堆。堆这种数据结构,类似于一个二分叉的树。树顶的元素一定要大于(或者小于)左右两个节点上的元素大小,树顶称之为根节点,可以没有左右子节点,但如果有子节点,必须是先有左节点,再有右节点,即可以没有右节点,只有左节点,但不能反过来。

      假设我们需要队列每次出来的元素都是整个队列中元素的最大值,就可以采用“大顶堆”,即根节点元素比左右元素都要大。这样,我们只需要在有新元素加进堆的时候,只需要通过某种算法调整到使整个队列中的数据还是一个“堆”状态,就可以在出队列的时候把最大的元素取出来。

      那么,在清楚这样一种数据结构之后,就很容易在新对象加进来之后,把它放到合适的位置了。首先,假设原来队列中的元素分别是1-N,那么首先把插进来的元素放在末尾,即放在N+1的位置。然后让它去和(N+1)/2位置的元素去比较(这个位置的元素正好是新插入元素的根节点元素)进行比较,如果新插入的元素小,那么说明新插入的元素所放入的位置是正确的。如果新插入的元素大,那么说明新插入的元素比原根节点大,应该和跟节点元素进行一次交换,然后继续和它的根节点元素相比较,知道把新加入的元素放到合适的地方。

      我们知道,这种“二叉堆”本质上将N个数分成了logN层数(2为底),这种方法相当于每次把新元素“上推一层”,所以整个的复杂度为O(logN)级别,比单纯的通过排序选出最大数据的时间复杂度O(N)快。所以,用这种“堆”的数据结构,当队列中有新加进来的元素的时候,能够很快找到新的最大(小)值。

      另一方面,当我们通过队列的方式取出来最大元素之后,整棵树的树顶不久“空”出来了吗?那么怎么样能够把整个队列的数据“恢复”成一个堆呢?其实也是有办法的,首先把队列最后一个元素先移到堆顶的位置,然后,让这个元素去和它的左右节点比较,如果比左小,就和左节点交换;如果比左大,比右小,就和右节点交换;如果比左、右节点都大,就说明放置的地方是正确的。通过这样的方法,就能够逐步把元素从顶至下“挪动”到合适的地方。可以看到,这种“挪动”方式其实也是每次往下进行一层,所以复杂度也是O(logN)(以2为底的对数)。

      通过“从底向上”,我们把新加入的元素放入合适的位置,通过“从上到下”,我们把整个队列元素恢复成“堆”的样子。这样,我们通过每次O(logN)的复杂度,就解决了新加入元素,然后把当前待处理队列中最大(小)的数放置在队列出口的操作。实现了每次都能“要事优先”。

      提高效率,就要少做事情。多选择有一种恰当的数据结构去简化问题。需要排序的地方就排序,不需要排序的地方就只用想办法把需要的数据找出来就好了。每周一篇算法学习收获总结,加油!

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1 初级排序算法 排序算法关注的主要是重新排列数组元素,其中每个元素都有一个主键。排序算法是将所有元素主键按某种方...
    深度沉迷学习阅读 5,349评论 0 1
  • 四. 走向世界之巅——快速排序 你可能会以为归并排序是最强的算法了,其实不然。回想一下,归并的时间效率虽然高,但空...
    Leesper阅读 5,843评论 9 7
  • 心存美好,则无可恼之事; 心存善良,则无可恨之人; 心若简单,世间纷扰皆成空。努力享受生活吧!!!
    安安忘忧草阅读 1,235评论 0 0
  • 自打脱离了“学生”这个身份以来,或许从我嘴里说出的最多的一句话,就是“速度”准确一点讲,它应该只是一个词汇抱歉,我...
    24e2f6668318阅读 1,079评论 0 0
  • 翻来翻去翻了好久就是睡不着,既然睡不着那就来乱写一通吧。 现在是凌晨两点十分,已经是第二天了…… 昨天是二蓉的生日...
    就是陈三岁阅读 1,657评论 3 1