有那么一类区间查询问题:给定一个无序的数组,查询一个给定区间中的第k大数。
简单的想法是把区间中的数排序,下标为k的数就是我们要找的,但是如果查询次数很多,即使是归并排序这种高效的排序算法也会超时,这时,我们要使用一种新的数据结构----划分树。
定义:它的每一个节点保存区间[lft,rht]所有元素,元素顺序与原数组(输入)相同,但是,两个子树的元素为该节点所有元素排序后(rht-lft+1)/2个进入左子树,其余的到右子树,同时维护一个num域,num[i]表示(lft,i)这个区间中有多少个点进入了左子树。
可以看到,建树的过程和快速排序的过程很相似,只不过在排序的过程中顺便记录下num这个数组,从而可以实现快速查询。
下面找个例子看一下这个算法的模拟过程:
在 [ 2 4 3 5 8 1 7 6 ] 中找区间[2,7]的第2小
① [ 2 4 3 5 8 1 7 6 ] // 原数组 [2,7]找第2小
② [ 2 4 3 1 ] [ 5 8 7 6 ] // 分成左右两组 知道[2,7]中有3个到左子树 故在答案左
③ [ 2 1 ] [ 4 3 ] [ 5 6 ] [ 8 7 ] // 同理 只有1个到左子树 故答案在右子树
④ [1] [2] [3] [4] [5] [6] [7] [8] // 一直迭代直到找到答案
关于模板:
这种与某种数据结构有关的算法,最好的模板就是封装的结构体或者类,这样的模板在稳定性和性能上都会有所保证,使用起来也会更加方便。