在lucene中,使用了很多常用的算法。还有一些很不错的算法,在学习lucene的过程中,顺便把这些算法也纪录下来,以后编程中可以直接使用。
1、在类TermHashPerField类中使用了快速排序:
2、多个数组求交集
这个是用在query查询的多个term取到倒排表以后,做交集得到结果
ConjunctionScorer.java 的 doNext函数是这个算法的实现,非常的简单,几行代码而已,非常的喜欢这个算法。
scorers[ ] 是以队列为单个元素的数组,首先用这些队列的第一个元素对数组进行排序,从0到length-1从小到大排好,然后将其中最大的scorers[length-1]队列的第一个元素赋于doc。然后每一个队列都与这个最大的doc做比较,如果第一个元素小于doc,那么这个队列弹出下一个元素与doc比较;如果相等,那么first加一,换成下一个队列与doc做比较;如果大于doc,那么将这个元素赋于doc,作为最大的。可以把这个些以队列为元素的数组当作一个环形的数组,这样就比较容易理解了。
firstScorer.advance(doc) 函数advance是从该数组中取大于等于doc号的doc
1、在类TermHashPerField类中使用了快速排序:
void quickSort(RawPostingList[] postings, int lo, int hi) {
if (lo >= hi)
return;
else if (hi == 1+lo) {
if (comparePostings(postings[lo], postings[hi]) > 0) {
final RawPostingList tmp = postings[lo];
postings[lo] = postings[hi];
postings[hi] = tmp;
}
return;
}
int mid = (lo + hi) >>> 1;
if (comparePostings(postings[lo], postings[mid]) > 0) {
RawPostingList tmp = postings[lo];
postings[lo] = postings[mid];
postings[mid] = tmp;
}
if (comparePostings(postings[mid], postings[hi]) > 0) {
RawPostingList tmp = postings[mid];
postings[mid] = postings[hi];
postings[hi] = tmp;
if (comparePostings(postings[lo], postings[mid]) > 0) {
RawPostingList tmp2 = postings[lo];
postings[lo] = postings[mid];
postings[mid] = tmp2;
}
}
int left = lo + 1;
int right = hi - 1;
if (left >= right)
return;
RawPostingList partition = postings[mid];
for (; ;) {
while (comparePostings(postings[right], partition) > 0)
--right;
while (left < right && comparePostings(postings[left], partition) <= 0)
++left;
if (left < right) {
RawPostingList tmp = postings[left];
postings[left] = postings[right];
postings[right] = tmp;
--right;
} else {
break;
}
}
quickSort(postings, lo, left);
quickSort(postings, left + 1, hi);
}
2、多个数组求交集
这个是用在query查询的多个term取到倒排表以后,做交集得到结果
ConjunctionScorer.java 的 doNext函数是这个算法的实现,非常的简单,几行代码而已,非常的喜欢这个算法。
scorers[ ] 是以队列为单个元素的数组,首先用这些队列的第一个元素对数组进行排序,从0到length-1从小到大排好,然后将其中最大的scorers[length-1]队列的第一个元素赋于doc。然后每一个队列都与这个最大的doc做比较,如果第一个元素小于doc,那么这个队列弹出下一个元素与doc比较;如果相等,那么first加一,换成下一个队列与doc做比较;如果大于doc,那么将这个元素赋于doc,作为最大的。可以把这个些以队列为元素的数组当作一个环形的数组,这样就比较容易理解了。
firstScorer.advance(doc) 函数advance是从该数组中取大于等于doc号的doc
private int doNext() throws IOException {
int first = 0;
int doc = scorers[scorers.length - 1].docID();//取最大的doc号给doc
Scorer firstScorer;
while ((firstScorer = scorers[first]).docID() < doc) {
doc = firstScorer.advance(doc);//从first数组中取大于等于doc号的元素,如果当前first大于doc,那么将doc设为当前first的元素
first = first == scorers.length - 1 ? 0 : first + 1;//first加一,如果当前到了length-1,那么相当于一个环形,从0开始
}
return doc;
}