• [ lucene高级 ] lucene中的算法PriorityQueue


    lucene的打分需要用到优先级队列,他是基于“堆”实现的。

    PriorityQueue是一个抽象方法,要求子类实现一个“比较方法”!

    PriorityQueue的源码如下:

    package org.apache.lucene.util;
    
    /**
     * Copyright 2004 The Apache Software Foundation
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *     http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    /** A PriorityQueue maintains a partial ordering of its elements such that the
      least element can always be found in constant time.  Put()'s and pop()'s
      require log(size) time. */
    public abstract class PriorityQueue {
      private Object[] heap;
      private int size;
      private int maxSize;
    
      /** Determines the ordering of objects in this priority queue.  Subclasses
        must define this one method. */
      protected abstract boolean lessThan(Object a, Object b);
    
      /** Subclass constructors must call this. */
      protected final void initialize(int maxSize) {
        size = 0;
        int heapSize = maxSize + 1;
        heap = new Object[heapSize];
        this.maxSize = maxSize;
      }
    
      /**
       * Adds an Object to a PriorityQueue in log(size) time.
       * If one tries to add more objects than maxSize from initialize
       * a RuntimeException (ArrayIndexOutOfBound) is thrown.
       */
      public final void put(Object element) {//如果队列未满,将ele添加到队尾,然后和父节点比较,使得较小的ele至于堆顶!
        size++;
        heap[size] = element;
        upHeap();
      }
    
      /**
       * Adds element to the PriorityQueue in log(size) time if either
       * the PriorityQueue is not full, or not lessThan(element, top()).
       * @param element
       * @return true if element is added, false otherwise.
       */
      public boolean insert(Object element){
        if(size < maxSize){
          put(element);
          return true;
        }
        else if(size > 0 && !lessThan(element, top())){//队列满,且ele大于队列中最小的ele!对于小根堆,top取得最小ele。
          heap[1] = element;
          adjustTop();
          return true;
        }
        else//队列满,ele小于队列中最小ele,则直接pass!
          return false;
       }
    
      /** Returns the least element of the PriorityQueue in constant time. */
      public final Object top() {
        if (size > 0)
          return heap[1];
        else
          return null;
      }
    
      /** Removes and returns the least element of the PriorityQueue in log(size)
        time. */
      public final Object pop() {
        if (size > 0) {
          Object result = heap[1];			  // save first value
          heap[1] = heap[size];			  // move last to first
          heap[size] = null;			  // permit GC of objects
          size--;
          downHeap();				  // 这里将堆顶ele弹出,继而用队列尾ele进行填充(heap[1]=heap[size]),那么需要重新调整heap的结构,使得其满足小根堆结构!
          return result;
        } else
          return null;
      }
    
      /** Should be called when the Object at top changes values.  Still log(n)
       * worst case, but it's at least twice as fast to <pre>
       *  { pq.top().change(); pq.adjustTop(); }
       * </pre> instead of <pre>
       *  { o = pq.pop(); o.change(); pq.push(o); }
       * </pre>
       */
      public final void adjustTop() {
        downHeap();
      }
    
    
      /** Returns the number of elements currently stored in the PriorityQueue. */
      public final int size() {
        return size;
      }
    
      /** Removes all entries from the PriorityQueue. */
      public final void clear() {
        for (int i = 0; i <= size; i++)
          heap[i] = null;
        size = 0;
      }
    
      private final void upHeap() {
        int i = size;
        Object node = heap[i];			  // save bottom node
        int j = i >>> 1;
        while (j > 0 && lessThan(node, heap[j])) {
          heap[i] = heap[j];			  // shift parents down
          i = j;
          j = j >>> 1;
        }
        heap[i] = node;				  // install saved node
      }
    
      private final void downHeap() {
        int i = 1;
        Object node = heap[i];			  // save top node
        int j = i << 1;				  // find smaller child
        int k = j + 1;
        if (k <= size && lessThan(heap[k], heap[j])) {
          j = k;
        }
        while (j <= size && lessThan(heap[j], node)) {
          heap[i] = heap[j];			  // shift up child
          i = j;
          j = i << 1;
          k = j + 1;
          if (k <= size && lessThan(heap[k], heap[j])) {
    	j = k;
          }
        }
        heap[i] = node;				  // install saved node
      }
    }
    

    测试:

    简单创建一个PriorityQueue的子类,如下:

    package com.fox.pq;
    
    import java.util.Random;
    
    import org.apache.lucene.util.PriorityQueue;
    
    /**
     * @author huangfox
     * @data 2012-7-11
     * @email huangfox009@126.com
     * @desc
     */
    public class MyPriorityQueue extends PriorityQueue {
    
    	public MyPriorityQueue(int i) {
    		initialize(i);
    	}
    
    	@Override
    	protected boolean lessThan(Object a, Object b) {
    		Integer a_ = (Integer) a;
    		Integer b_ = (Integer) b;
    		return a_ < b_;
    	}
    
    	public static void main(String[] f) {
    		MyPriorityQueue priQueue = new MyPriorityQueue(10);
    		Random r = new Random();
    		for (int i = 0; i < 25; i++) {
    			priQueue.insert(r.nextInt(100));
    		}
    		// 打印结果
    		Integer v = (Integer) priQueue.pop();
    		while (v != null) {
    			System.out.println(v);
    			v = (Integer) priQueue.pop();
    		}
    	}
    }
    
  • 相关阅读:
    面试题(三)
    面试题(二)
    经典面试题(一)
    $.ajax()实现简单计算器
    [hdu5373 The shortest problem]模拟
    [hdu5371 Hotaru's problem]最大回文半径
    [hdu5372 Segment Game]树状数组
    [zoj3813]Alternating Sum 公式化简,线段树
    [hdu5348]图上找环,删环
    [hdu5360]贪心
  • 原文地址:https://www.cnblogs.com/huangfox/p/2586232.html
Copyright © 2020-2023  润新知