⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fibonacciheap.java

📁 nutch搜索的改进型工具和优化爬虫的相关工具
💻 JAVA
字号:
/* Copyright (c) 2003 The Nutch Organization.  All rights reserved.   */
/* Use subject to the conditions in http://www.nutch.org/LICENSE.txt. */

package net.nutch.util;

import java.util.Arrays;
import java.util.HashMap;

/**
 * A Fibonacci Heap, as described in <i>Introduction to Algorithms</i> by
 * Charles E. Leiserson, Thomas H. Cormen, Ronald L. Rivest.
 *
 * <p>
 *
 * A Fibonacci heap is a very efficient data structure for priority
 * queuing.  
 *
 */
public class FibonacciHeap {
  private FibonacciHeapNode min;
  private HashMap itemsToNodes;

  // private node class
  private static class FibonacciHeapNode {
    private Object userObject;
    private int priority;

    private FibonacciHeapNode parent;
    private FibonacciHeapNode prevSibling;
    private FibonacciHeapNode nextSibling;
    private FibonacciHeapNode child;
    private int degree;
    private boolean mark;

    FibonacciHeapNode(Object userObject, int priority) {
      this.userObject= userObject;
      this.priority= priority;

      this.parent= null;
      this.prevSibling= this;
      this.nextSibling= this;
      this.child= null;
      this.degree= 0;
      this.mark= false;
    }

    public String toString() {
      return "["+userObject+", "+degree+"]";
    }
  }

  /**
   * Creates a new <code>FibonacciHeap</code>.
   */
  public FibonacciHeap() {
    this.min= null;
    this.itemsToNodes= new HashMap();
  }

  /**
   *  Adds the Object <code>item</code>, with the supplied
   *  <code>priority</code>.
   */
  public void add(Object item, int priority) {
    if (itemsToNodes.containsKey(item))
      throw new IllegalStateException("heap already contains item! (item= "
                                      + item + ")");
    FibonacciHeapNode newNode= new FibonacciHeapNode(item, priority);
    itemsToNodes.put(item, newNode);

    if (min == null) {
      min= newNode;
    } else {
      concatenateSiblings(newNode, min);
      if (newNode.priority < min.priority) 
        min= newNode;
    }
  }

  /**
   * Returns <code>true</code> if <code>item</code> exists in this
   * <code>FibonacciHeap</code>, false otherwise.
   */
  public boolean contains(Object item) {
    return itemsToNodes.containsKey(item);
  }

  // makes x's nextSibling and prevSibling point to itself
  private void removeFromSiblings(FibonacciHeapNode x) {
    if (x.nextSibling == x) 
      return;
    x.nextSibling.prevSibling= x.prevSibling;
    x.prevSibling.nextSibling= x.nextSibling;
    x.nextSibling= x;
    x.prevSibling= x;
  }

  // joins siblings lists of a and b
  private void concatenateSiblings(FibonacciHeapNode a, FibonacciHeapNode b) {
    a.nextSibling.prevSibling= b;
    b.nextSibling.prevSibling= a;
    FibonacciHeapNode origAnext= a.nextSibling;
    a.nextSibling= b.nextSibling;
    b.nextSibling= origAnext;
  }

  /**
   * Returns the same Object that {@link #popMin()} would, without
   * removing it.
   */ 
  public Object peekMin() {
    if (min == null) 
      return null;
    return min.userObject;
  }

  /**
   * Returns the number of objects in the heap.
   */
  public int size() {
    return itemsToNodes.size();
  }

  /**
   * Returns the object which has the <em>lowest</em> priority in the
   * heap.  If the heap is empty, <code>null</code> is returned.
   */
  public Object popMin() {
    if (min == null) 
      return null;
    if (min.child != null) {
      FibonacciHeapNode tmp= min.child;
      // rempve parent pointers to min
      while (tmp.parent != null) {
        tmp.parent= null;
        tmp= tmp.nextSibling;
      }
      // add children of min to root list
      concatenateSiblings(tmp, min);
    }
    // remove min from root list
    FibonacciHeapNode oldMin= min;
    if (min.nextSibling == min) {
      min= null;
    } else {
      min= min.nextSibling;
      removeFromSiblings(oldMin);
      consolidate();
    }
    itemsToNodes.remove(oldMin.userObject);
    return oldMin.userObject;
  }

  // consolidates heaps of same degree
  private void consolidate() {
    int size= size();
    FibonacciHeapNode[] newRoots= new FibonacciHeapNode[size];

    FibonacciHeapNode node= min;
    FibonacciHeapNode start= min;
    do {
      FibonacciHeapNode x= node;
      int currDegree= node.degree;
      while (newRoots[currDegree] != null) {
        FibonacciHeapNode y= newRoots[currDegree];
        if (x.priority > y.priority) {
          FibonacciHeapNode tmp= x;
          x= y;
          y= tmp;
        }
        if (y == start) {
          start= start.nextSibling;
        }
        if (y == node) {
          node= node.prevSibling;
        }
        link(y, x);
        newRoots[currDegree++]= null;
      }
      newRoots[currDegree]= x;
      node= node.nextSibling;
    } while (node != start);

    min= null;
    for (int i= 0; i < newRoots.length; i++) 
      if (newRoots[i] != null) {
        if ( (min == null) 
             || (newRoots[i].priority < min.priority) )
          min= newRoots[i];
      }
  }

  // links y under x
  private void link(FibonacciHeapNode y, FibonacciHeapNode x) {
    removeFromSiblings(y);
    y.parent= x;
    if (x.child == null) 
      x.child= y;
    else 
      concatenateSiblings(x.child, y);
    x.degree++;
    y.mark= false;
  }

  /**
   * Decreases the <code>priority</code> value associated with
   * <code>item</code>.
   *
   * <p>
   *
   * <code>item<code> must exist in the heap, and it's current
   * priority must be greater than <code>priority</code>.  
   *
   * @throws IllegalStateException if <code>item</code> does not exist
   * in the heap, or if <code>item</code> already has an equal or
   * lower priority than the supplied<code>priority</code>.
   */
  public void decreaseKey(Object item, int priority) {
    FibonacciHeapNode node= 
      (FibonacciHeapNode) itemsToNodes.get(item);
    if (node == null) 
      throw new IllegalStateException("No such element: " + item);
    if (node.priority < priority) 
      throw new IllegalStateException("decreaseKey(" + item + ", " 
                                      + priority + ") called, but priority="
                                      + node.priority);
    node.priority= priority;
    FibonacciHeapNode parent= node.parent;
    if ( (parent != null) && (node.priority < parent.priority) ) {
      cut(node, parent);
      cascadingCut(parent);
    }
    if (node.priority < min.priority) 
      min= node;

  }

  // cut node x from below y
  private void cut(FibonacciHeapNode x, FibonacciHeapNode y) {
    // remove x from y's children
    if (y.child == x) 
      y.child= x.nextSibling;
    if (y.child == x) 
      y.child= null;

    y.degree--;
    removeFromSiblings(x);
    concatenateSiblings(x, min);
    x.parent= null;
    x.mark= false;
                
  }

  private void cascadingCut(FibonacciHeapNode y) {
    FibonacciHeapNode z= y.parent;
    if (z != null) {
      if (!y.mark) {
        y.mark= true;
      } else {
        cut(y, z);
        cascadingCut(z);
      }
    }
  }

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -