MATSIM
NodeMinHeap.java
Go to the documentation of this file.
1 package org.matsim.core.router.speedy;
2 
3 import java.util.NoSuchElementException;
4 
8 class NodeMinHeap {
9  private final int[] heap;
10  private final int[] pos;
11  private int size = 0;
12  private final CostGetter costGetter;
13  private final CostSetter costSetter;
14 
15  public interface CostGetter {
16  double getCost(int index);
17  }
18 
19  public interface CostSetter {
20  void setCost(int index, double cost);
21  }
22 
23  NodeMinHeap(int nodeCount, CostGetter costGetter, CostSetter costSetter) {
24  this.heap = new int[nodeCount]; // worst case: every node is part of the heap
25  this.pos = new int[nodeCount];
26  this.costGetter = costGetter;
27  this.costSetter = costSetter;
28  }
29 
30  void insert(int node) {
31  int i = this.size;
32  this.size++;
33 
34  double nodeCost = this.costGetter.getCost(node);
35  // sift up
36  int parent = parent(i);
37  while (i > 0 && nodeCost < this.costGetter.getCost(this.heap[parent])) {
38  this.heap[i] = this.heap[parent];
39  this.pos[this.heap[parent]] = i;
40  i = parent;
41  parent = parent(parent);
42  }
43  this.heap[i] = node;
44  this.pos[node] = i;
45  }
46 
47  void decreaseKey(int node, double cost) {
48  int i;
49  for (i = 0; i < this.size; i++) {
50  if (this.heap[i] == node) {
51  break;
52  }
53  }
54  if (this.costGetter.getCost(this.heap[i]) < cost) {
55  throw new IllegalArgumentException("existing cost is already smaller than new cost.");
56  }
57 
58  this.costSetter.setCost(node, cost);
59 
60  // sift up
61  int parent = parent(i);
62  while (i > 0 && cost < this.costGetter.getCost(this.heap[parent])) {
63  this.heap[i] = this.heap[parent];
64  this.pos[this.heap[parent]] = i;
65  i = parent;
66  parent = parent(parent);
67  }
68  this.heap[i] = node;
69  this.pos[node] = i;
70  }
71 
72  int poll() {
73  if (this.size == 0) {
74  throw new NoSuchElementException("heap is empty");
75  }
76  if (this.size == 1) {
77  this.size--;
78  return this.heap[0];
79  }
80 
81  int root = this.heap[0];
82 
83  // remove the last item, set it as new root
84  int lastNode = this.heap[this.size - 1];
85  this.size--;
86  this.heap[0] = lastNode;
87  this.pos[lastNode] = 0;
88 
89  // sift down
90  minHeapify(0);
91 
92  return root;
93  }
94 
95  int peek() {
96  if (this.size == 0) {
97  throw new NoSuchElementException("heap is empty");
98  }
99  return this.heap[0];
100  }
101 
102  int size() {
103  return this.size;
104  }
105 
106  boolean isEmpty() {
107  return this.size == 0;
108  }
109 
110  void clear() {
111  this.size = 0;
112  }
113 
114  private void minHeapify(int i) {
115  int left = left(i);
116  int right = right(i);
117  int smallest = i;
118 
119  if (left <= (this.size - 1) && this.costGetter.getCost(this.heap[left]) < this.costGetter.getCost(this.heap[i])) {
120  smallest = left;
121  }
122  if (right <= (this.size - 1) && this.costGetter.getCost(this.heap[right]) < this.costGetter.getCost(this.heap[smallest])) {
123  smallest = right;
124  }
125  if (smallest != i) {
126  swap(i, smallest);
127  minHeapify(smallest);
128  }
129  }
130 
131  private int right(int i) {
132  return 2 * i + 2;
133  }
134 
135  private int left(int i) {
136  return 2 * i + 1;
137  }
138 
139  private int parent(int i) {
140  return (i - 1) / 2;
141  }
142 
143  private void swap(int i, int parent) {
144  int tmp = this.heap[parent];
145  this.heap[parent] = this.heap[i];
146  this.pos[this.heap[i]] = parent;
147  this.heap[i] = tmp;
148  this.pos[tmp] = i;
149  }
150 }