搜索中的排序优化

来源:互联网 发布:龙之谷数据库怎么修改 编辑:程序博客网 时间:2024/04/29 21:12

搜索引擎中有一个分页的需求,按照某个字段排序,从start位置开始,返回num个doc;

算法接口: void sort_result(dococument docs[], int size, int start, int num, int sort_field)

使用3种不同算法分别实现,观察效果,选择排序,堆排序,快速排序;K = start + num


算法一:选择排序(selection sort)

selection sort的简单变种,只排序前start+num=K即可。

时间复杂度 O(K*N)


算法二:堆排序(heap sort)

1. 先对数组中前K个建最大堆; O(K)

2. 剩下的N-K个分别与堆顶元素比较,需要的话则调整堆; (N-K)lgK

3. 对K最大堆进行num次调整,使从start开始的num个元素有序; num lgK

时间复杂度 O((N-K)lgK + K)


算法三:快速排序(quick sort)

1. 对N个元素进行partition,获得pivot

2. 如果pivot比start小,则递归在pivot之后调用qsort(docs + pivot, size - pivot, start - pivot, end - pivot)

3. 如果pivot比start+num大,则递归在pivot之前qsort(docs, pivot, start, end)

4. 如果pivot落在start到start+num之间,分别对两部分进行递归调用

qsort(docs, pivot, start, pivot); qsort(docs + pivot, n-pivot, 0, end - pivot)

时间复杂度 O(N)


实际测试分析

从时间复杂度分析可知,选择排序O(K*N), 堆排序O((N-K)lgK + K),快速排序O(N);

选择排序几乎可以被排除,不管K取值多少,K>2后几乎没任何优势, 这点和代码测试结果吻合。

堆排序呈现特点是K取值小,或者特别大接近N时,速度会比较快;K在N/2左右时,费时最大。与测试结果吻合。

快速排序时间总体比较稳定,和K的取值几乎无关,与代码测试吻合。


用一份random的数组,长度5w进行测试,每个元素都不同;

quicksort时间不管K的取值,都比较稳定;K取值在1000以内,heapsort比quicksort快,大于1000后,quicksort快。

5w数组中大多数元素都相同,只有100个不同取值

不管K的取值,几乎都是heapsort占优,因为元素单一,第二阶段的堆调整几乎是N的时间,而不是NlgK快速排序退化严重,因为pivot位置问题

5w数组中,所有元素都是同一个取值,quicksort退化为插入排序。


在实际项目应用中,K的取值一般较小,所以heapsort比较合适;

而且对于有些排序字段,值的重复度很高,quicksort几乎退化为插入排序;而heapsort由于减少了堆调整次数,跑的更快。

所以在搜索的排序中,全部用heapsort,综合来看是比较好的。

最新更新:

doc中都会存在一个nid的概念,用这个变量可以保证两个doc永远不会相等,这样就没有是否stable的区分了。

start+num<2000时用heapsort,否则用quicksort