http://sjjp.tjuci.edu.cn/sjjg/datastructure/ds/web/paixu/paixu8.4.2.2.htm
堆(Heap)分为小根堆和大根堆两种,对于一个小根堆,它是具有如下特性的一棵完全二叉树: |
定义:堆的一种,即根节点小于它的左孩子,也小于它的右孩子. 小根椎的构建: 首先,将无序序列变成完全二叉树的形式. 排序 : 然后,从最后一个叶节点的父节点开始,往前逐个检查各个节点,看其是不是符合父节点小于它的子节点,如果不小于,则将它的 子节点中最小的那个节点与父节点对换;否则,不交换,继续往前检查.直到根节点为最小节点,然后将其与最后一个节点交换.此后,继续检查各个节点是不是满足最小根要求,如果不满足,则时行调整,直到所有的节点都满足,到此,第一轮调整结束. 下一步,将上一步得到的要节点与上次交换的节点的前一个节点交换,继续和上一步一样的调整.得到第二轮调整序列. 重复上两步,直到待调整的节点个数为1. 在最小堆里插入节点: 将要插入的节点X放在原来堆的完全二叉树的最后一个位置,然后不断地往上调整,直到X 调不动为止. |
假设我们现在有两个集合,集合 1 存放当前数中较小的一半,集合 2 中存放当前数中较大的一半,如果集合中数的个数是奇数,那么把中位数单独列出来,记为mid。
我们记录集合 1 中的最大元素是 lmax , 集合 2 中的最小元素是 rmin
先看查询操作:如果集合有奇数个数,中位数就是 mid。如果集合有偶数个数,中位数等于(lmax+rmin)/2。
插入操作:分两种情况
(1).当前集合中有偶数个元素。
如果有 lmax <= x <= rmin,显然 mid=x 即可。
如果有 lmax > x , 显然 mid = lmax , 把 lmax 从集合 1 删除,x 插入集合 1
如果有 rmin < x , 显然 mid = rmin , 把 rmin 从集合 2 删除,x 插入集合 2
(2).当前集合中有奇数数个元素
如果 x >= mid ,那么把 mid 插入集合 1,x 插入集合 2
如果 x < mid ,那么把 mid 插入集合 2,x 插入集合 1
可以看到,上面的操作中涉及到对取出集合中的最大或最小元素,由于 n 很大,需要比较快的取得最大和最小数,因此需要堆来支持这些操作。把集合 1 设置成大根堆,集合 2 设置成小根堆,这样取元素,删除,插入的操作都是 logn,总的复杂度是 o(nlogn)