PageRenderTime 47ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/GeoRouting/branches/Network/FibHeap.cs

http://georouting-hyperpath.googlecode.com/
C# | 680 lines | 339 code | 115 blank | 226 comment | 58 complexity | 660b250ebffe11bf1c1ba718ddc4745e MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. namespace NetworkLib.FibHeap
  6. {
  7. public class FibonacciHeap<T>
  8. {
  9. //~ Static fields/initializers ---------------------------------------------
  10. private static double oneOverLogPhi =
  11. 1.0 / Math.Log((1.0 + Math.Sqrt(5.0)) / 2.0);
  12. //~ Instance fields --------------------------------------------------------
  13. /**
  14. * Points to the minimum node in the heap.
  15. */
  16. private FibonacciHeapNode<T> minNode;
  17. /**
  18. * Number of nodes in the heap.
  19. */
  20. private int nNodes;
  21. //~ Constructors -----------------------------------------------------------
  22. /**
  23. * Constructs a FibonacciHeap object that contains no elements.
  24. */
  25. public FibonacciHeap()
  26. {
  27. } // FibonacciHeap
  28. //~ Methods ----------------------------------------------------------------
  29. /**
  30. * Tests if the Fibonacci heap is empty or not. Returns true if the heap is
  31. * empty, false otherwise.
  32. *
  33. * <p>Running time: O(1) actual</p>
  34. *
  35. * @return true if the heap is empty, false otherwise
  36. */
  37. public bool isEmpty()
  38. {
  39. return minNode == null;
  40. }
  41. // isEmpty
  42. /**
  43. * Removes all elements from this heap.
  44. */
  45. public void clear()
  46. {
  47. minNode = null;
  48. nNodes = 0;
  49. }
  50. // clear
  51. /**
  52. * Decreases the key value for a heap node, given the new value to take on.
  53. * The structure of the heap may be changed and will not be consolidated.
  54. *
  55. * <p>Running time: O(1) amortized</p>
  56. *
  57. * @param x node to decrease the key of
  58. * @param k new key value for node x
  59. *
  60. * @exception IllegalArgumentException Thrown if k is larger than x.key
  61. * value.
  62. */
  63. public void decreaseKey(FibonacciHeapNode<T> x, double k)
  64. {
  65. if (k > x.key)
  66. {
  67. throw new Exception(
  68. "decreaseKey() got larger key value");
  69. }
  70. x.key = k;
  71. FibonacciHeapNode<T> y = x.parent;
  72. if ((y != null) && (x.key < y.key))
  73. {
  74. cut(x, y);
  75. cascadingCut(y);
  76. }
  77. if (x.key < minNode.key)
  78. {
  79. minNode = x;
  80. }
  81. }
  82. //decreaseKey
  83. /**
  84. * Deletes a node from the heap given the reference to the node. The trees
  85. * in the heap will be consolidated, if necessary. This operation may fail
  86. * to remove the correct element if there are nodes with key value
  87. * -Infinity.
  88. *
  89. * <p>Running time: O(log n) amortized</p>
  90. *
  91. * @param x node to remove from heap
  92. */
  93. public void delete(FibonacciHeapNode<T> x)
  94. {
  95. // make x as small as possible
  96. decreaseKey(x, Double.NegativeInfinity);
  97. // remove the smallest, which decreases n also
  98. removeMin();
  99. }
  100. // delete
  101. /**
  102. * Inserts a new data element into the heap. No heap consolidation is
  103. * performed at this time, the new node is simply inserted into the root
  104. * list of this heap.
  105. *
  106. * <p>Running time: O(1) actual</p>
  107. *
  108. * @param node new node to insert into heap
  109. * @param key key value associated with data object
  110. */
  111. public void insert(FibonacciHeapNode<T> node, double key)
  112. {
  113. node.key = key;
  114. // concatenate node into min list
  115. if (minNode != null)
  116. {
  117. node.left = minNode;
  118. node.right = minNode.right;
  119. minNode.right = node;
  120. node.right.left = node;
  121. if (key < minNode.key)
  122. {
  123. minNode = node;
  124. }
  125. }
  126. else
  127. {
  128. minNode = node;
  129. }
  130. nNodes++;
  131. }
  132. // insert
  133. /**
  134. * Returns the smallest element in the heap. This smallest element is the
  135. * one with the minimum key value.
  136. *
  137. * <p>Running time: O(1) actual</p>
  138. *
  139. * @return heap node with the smallest key
  140. */
  141. public FibonacciHeapNode<T> min()
  142. {
  143. return minNode;
  144. }
  145. // min
  146. /**
  147. * Removes the smallest element from the heap. This will cause the trees in
  148. * the heap to be consolidated, if necessary.
  149. *
  150. * <p>Running time: O(log n) amortized</p>
  151. *
  152. * @return node with the smallest key
  153. */
  154. public FibonacciHeapNode<T> removeMin()
  155. {
  156. FibonacciHeapNode<T> z = minNode;
  157. if (z != null)
  158. {
  159. int numKids = z.degree;
  160. FibonacciHeapNode<T> x = z.child;
  161. FibonacciHeapNode<T> tempRight;
  162. // for each child of z do...
  163. while (numKids > 0)
  164. {
  165. tempRight = x.right;
  166. // remove x from child list
  167. x.left.right = x.right;
  168. x.right.left = x.left;
  169. // add x to root list of heap
  170. x.left = minNode;
  171. x.right = minNode.right;
  172. minNode.right = x;
  173. x.right.left = x;
  174. // set parent[x] to null
  175. x.parent = null;
  176. x = tempRight;
  177. numKids--;
  178. }
  179. // remove z from root list of heap
  180. z.left.right = z.right;
  181. z.right.left = z.left;
  182. if (z == z.right)
  183. {
  184. minNode = null;
  185. }
  186. else
  187. {
  188. minNode = z.right;
  189. consolidate();
  190. }
  191. // decrement size of heap
  192. nNodes--;
  193. }
  194. return z;
  195. }
  196. // removeMin
  197. /**
  198. * Returns the size of the heap which is measured in the number of elements
  199. * contained in the heap.
  200. *
  201. * <p>Running time: O(1) actual</p>
  202. *
  203. * @return number of elements in the heap
  204. */
  205. public int size()
  206. {
  207. return nNodes;
  208. }
  209. // size
  210. /**
  211. * Joins two Fibonacci heaps into a new one. No heap consolidation is
  212. * performed at this time. The two root lists are simply joined together.
  213. *
  214. * <p>Running time: O(1) actual</p>
  215. *
  216. * @param h1 first heap
  217. * @param h2 second heap
  218. *
  219. * @return new heap containing h1 and h2
  220. */
  221. public static FibonacciHeap<T> union(
  222. FibonacciHeap<T> h1,
  223. FibonacciHeap<T> h2)
  224. {
  225. FibonacciHeap<T> h = new FibonacciHeap<T>();
  226. if ((h1 != null) && (h2 != null))
  227. {
  228. h.minNode = h1.minNode;
  229. if (h.minNode != null)
  230. {
  231. if (h2.minNode != null)
  232. {
  233. h.minNode.right.left = h2.minNode.left;
  234. h2.minNode.left.right = h.minNode.right;
  235. h.minNode.right = h2.minNode;
  236. h2.minNode.left = h.minNode;
  237. if (h2.minNode.key < h1.minNode.key)
  238. {
  239. h.minNode = h2.minNode;
  240. }
  241. }
  242. }
  243. else
  244. {
  245. h.minNode = h2.minNode;
  246. }
  247. h.nNodes = h1.nNodes + h2.nNodes;
  248. }
  249. return h;
  250. }
  251. // union
  252. /**
  253. * Creates a String representation of this Fibonacci heap.
  254. *
  255. * @return String of this.
  256. */
  257. public override String ToString()
  258. {
  259. if (minNode == null)
  260. {
  261. return "FibonacciHeap=[]";
  262. }
  263. // create a new stack and put root on it
  264. Stack<FibonacciHeapNode<T>> stack = new Stack<FibonacciHeapNode<T>>();
  265. stack.Push(minNode);
  266. StringBuilder buf = new StringBuilder(512);
  267. buf.Append("FibonacciHeap=[");
  268. // do a simple breadth-first traversal on the tree
  269. while (stack.Count != 0)
  270. {
  271. FibonacciHeapNode<T> curr = stack.Pop();
  272. buf.Append(curr);
  273. buf.Append(", ");
  274. if (curr.child != null)
  275. {
  276. stack.Push(curr.child);
  277. }
  278. FibonacciHeapNode<T> start = curr;
  279. curr = curr.right;
  280. while (curr != start)
  281. {
  282. buf.Append(curr);
  283. buf.Append(", ");
  284. if (curr.child != null)
  285. {
  286. stack.Push(curr.child);
  287. }
  288. curr = curr.right;
  289. }
  290. }
  291. buf.Append(']');
  292. return buf.ToString();
  293. }
  294. // toString
  295. /**
  296. * Performs a cascading cut operation. This cuts y from its parent and then
  297. * does the same for its parent, and so on up the tree.
  298. *
  299. * <p>Running time: O(log n); O(1) excluding the recursion</p>
  300. *
  301. * @param y node to perform cascading cut on
  302. */
  303. protected void cascadingCut(FibonacciHeapNode<T> y)
  304. {
  305. FibonacciHeapNode<T> z = y.parent;
  306. // if there's a parent...
  307. if (z != null)
  308. {
  309. // if y is unmarked, set it marked
  310. if (!y.mark)
  311. {
  312. y.mark = true;
  313. }
  314. else
  315. {
  316. // it's marked, cut it from parent
  317. cut(y, z);
  318. // cut its parent as well
  319. cascadingCut(z);
  320. }
  321. }
  322. }
  323. // cascadingCut
  324. public void consolidate()
  325. {
  326. int arraySize =
  327. ((int)Math.Floor(Math.Log(nNodes) * oneOverLogPhi)) + 1;
  328. List<FibonacciHeapNode<T>> array =
  329. new List<FibonacciHeapNode<T>>(arraySize);
  330. // Initialize degree array
  331. for (int i = 0; i < arraySize; i++)
  332. {
  333. array.Add(null);
  334. }
  335. // Find the number of root nodes.
  336. int numRoots = 0;
  337. FibonacciHeapNode<T> x = minNode;
  338. if (x != null)
  339. {
  340. numRoots++;
  341. x = x.right;
  342. while (x != minNode)
  343. {
  344. numRoots++;
  345. x = x.right;
  346. }
  347. }
  348. // For each node in root list do...
  349. while (numRoots > 0)
  350. {
  351. // Access this node's degree..
  352. int d = x.degree;
  353. FibonacciHeapNode<T> next = x.right;
  354. // ..and see if there's another of the same degree.
  355. for (; ; )
  356. {
  357. FibonacciHeapNode<T> y = array[d];
  358. if (y == null)
  359. {
  360. // Nope.
  361. break;
  362. }
  363. // There is, make one of the nodes a child of the other.
  364. // Do this based on the key value.
  365. if (x.key > y.key)
  366. {
  367. FibonacciHeapNode<T> temp = y;
  368. y = x;
  369. x = temp;
  370. }
  371. // FibonacciHeapNode<T> y disappears from root list.
  372. link(y, x);
  373. // We've handled this degree, go to next one.
  374. array[d] = null;
  375. d++;
  376. }
  377. // Save this node for later when we might encounter another
  378. // of the same degree.
  379. array[d] = x;
  380. // Move forward through list.
  381. x = next;
  382. numRoots--;
  383. }
  384. // Set min to null (effectively losing the root list) and
  385. // reconstruct the root list from the array entries in array[].
  386. minNode = null;
  387. for (int i = 0; i < arraySize; i++)
  388. {
  389. FibonacciHeapNode<T> y = array[i];
  390. if (y == null)
  391. {
  392. continue;
  393. }
  394. // We've got a live one, add it to root list.
  395. if (minNode != null)
  396. {
  397. // First remove node from root list.
  398. y.left.right = y.right;
  399. y.right.left = y.left;
  400. // Now add to root list, again.
  401. y.left = minNode;
  402. y.right = minNode.right;
  403. minNode.right = y;
  404. y.right.left = y;
  405. // Check if this is a new min.
  406. if (y.key < minNode.key)
  407. {
  408. minNode = y;
  409. }
  410. }
  411. else
  412. {
  413. minNode = y;
  414. }
  415. }
  416. }
  417. // consolidate
  418. /**
  419. * The reverse of the link operation: removes x from the child list of y.
  420. * This method assumes that min is non-null.
  421. *
  422. * <p>Running time: O(1)</p>
  423. *
  424. * @param x child of y to be removed from y's child list
  425. * @param y parent of x about to lose a child
  426. */
  427. protected void cut(FibonacciHeapNode<T> x, FibonacciHeapNode<T> y)
  428. {
  429. // remove x from childlist of y and decrement degree[y]
  430. x.left.right = x.right;
  431. x.right.left = x.left;
  432. y.degree--;
  433. // reset y.child if necessary
  434. if (y.child == x)
  435. {
  436. y.child = x.right;
  437. }
  438. if (y.degree == 0)
  439. {
  440. y.child = null;
  441. }
  442. // add x to root list of heap
  443. x.left = minNode;
  444. x.right = minNode.right;
  445. minNode.right = x;
  446. x.right.left = x;
  447. // set parent[x] to nil
  448. x.parent = null;
  449. // set mark[x] to false
  450. x.mark = false;
  451. }
  452. // cut
  453. /**
  454. * Make node y a child of node x.
  455. *
  456. * <p>Running time: O(1) actual</p>
  457. *
  458. * @param y node to become child
  459. * @param x node to become parent
  460. */
  461. protected void link(FibonacciHeapNode<T> y, FibonacciHeapNode<T> x)
  462. {
  463. // remove y from root list of heap
  464. y.left.right = y.right;
  465. y.right.left = y.left;
  466. // make y a child of x
  467. y.parent = x;
  468. if (x.child == null)
  469. {
  470. x.child = y;
  471. y.right = y;
  472. y.left = y;
  473. }
  474. else
  475. {
  476. y.left = x.child;
  477. y.right = x.child.right;
  478. x.child.right = y;
  479. y.right.left = y;
  480. }
  481. // increase degree[x]
  482. x.degree++;
  483. // set mark[y] false
  484. y.mark = false;
  485. }
  486. // link
  487. }
  488. public class FibonacciHeapNode<T>
  489. {
  490. //~ Instance fields --------------------------------------------------------
  491. /**
  492. * Node data.
  493. */
  494. T data;
  495. /**
  496. * first child node
  497. */
  498. public FibonacciHeapNode<T> child;
  499. /**
  500. * left sibling node
  501. */
  502. public FibonacciHeapNode<T> left;
  503. /**
  504. * parent node
  505. */
  506. public FibonacciHeapNode<T> parent;
  507. /**
  508. * right sibling node
  509. */
  510. public FibonacciHeapNode<T> right;
  511. /**
  512. * true if this node has had a child removed since this node was added to
  513. * its parent
  514. */
  515. public bool mark;
  516. /**
  517. * key value for this node
  518. */
  519. public double key;
  520. /**
  521. * number of children of this node (does not count grandchildren)
  522. */
  523. public int degree;
  524. //~ Constructors -----------------------------------------------------------
  525. /**
  526. * Default constructor. Initializes the right and left pointers, making this
  527. * a circular doubly-linked list.
  528. *
  529. * @param data data for this node
  530. */
  531. public FibonacciHeapNode(T data)
  532. {
  533. right = this;
  534. left = this;
  535. this.data = data;
  536. }
  537. //~ Methods ----------------------------------------------------------------
  538. /**
  539. * Obtain the key for this node.
  540. *
  541. * @return the key
  542. */
  543. public double getKey()
  544. {
  545. return key;
  546. }
  547. /**
  548. * Obtain the data for this node.
  549. */
  550. public T getData()
  551. {
  552. return data;
  553. }
  554. /**
  555. * Return the string representation of this object.
  556. *
  557. * @return string representing this object
  558. */
  559. public override String ToString()
  560. {
  561. return key.ToString();
  562. }
  563. // toString
  564. }
  565. }