bintree_splay.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /*********************** -*- Mode: C -*- ***********************
  2. * File : bintree_splay.c
  3. *---------------------------------------------------------------
  4. * Description
  5. * ===========
  6. * An implementation of top-down splaying
  7. * D. Sleator <sleator@cs.cmu.edu>
  8. * March 1992
  9. *
  10. * "Splay trees", or "self-adjusting search trees" are a simple and
  11. * efficient data structure for storing an ordered set. The data
  12. * structure consists of a binary tree, without parent pointers, and
  13. * no additional fields. It allows searching, insertion, deletion,
  14. * deletemin, deletemax, splitting, joining, and many other
  15. * operations, all with amortized logarithmic performance. Since the
  16. * trees adapt to the sequence of requests, their performance on real
  17. * access patterns is typically even better. Splay trees are
  18. * described in a number of texts and papers [1,2,3,4,5].
  19. *
  20. * The code here is adapted from simple top-down splay, at the bottom
  21. * of page 669 of [3]. It can be obtained via anonymous ftp from
  22. * spade.pc.cs.cmu.edu in directory /usr/sleator/public.
  23. *
  24. * The chief modification here is that the splay operation works even
  25. * if the item being splayed is not in the tree, and even if the tree
  26. * root of the tree is NULL. So the line:
  27. *
  28. * t = splay(i, t);
  29. *
  30. * causes it to search for item with key i in the tree rooted at t.
  31. * If it's there, it is splayed to the root. If it isn't there,
  32. * then the node put at the root is the last one before NULL that
  33. * would have been reached in a normal binary search for i. (It's a
  34. * neighbor of i in the tree.) This allows many other operations to
  35. * be easily implemented, as shown below.
  36. *
  37. * [1] "Fundamentals of data structures in C", Horowitz, Sahni,
  38. * and Anderson-Freed, Computer Science Press, pp 542-547.
  39. * [2] "Data Structures and Their Algorithms", Lewis and Denenberg,
  40. * Harper Collins, 1991, pp 243-251.
  41. * [3] "Self-adjusting Binary Search Trees" Sleator and Tarjan,
  42. * JACM Volume 32, No 3, July 1985, pp 652-686.
  43. * [4] "Data Structure and Algorithm Analysis", Mark Weiss,
  44. * Benjamin Cummins, 1992, pp 119-130.
  45. * [5] "Data Structures, Algorithms, and Performance", Derick Wood,
  46. * Addison-Wesley, 1993, pp 367-375.
  47. *
  48. * The following code was written by Daniel Sleator, and is released
  49. * in the public domain.
  50. *
  51. *---------------------------------------------------------------
  52. * Author : Graeme McKerrell
  53. * Created On : Wed Jan 28 16:29:28 2004
  54. * Status : TESTED
  55. *---------------------------------------------------------------
  56. * HISTORY
  57. * 7-Dec-2004 Graeme McKerrell
  58. * Renamed to the "lub_" namespace
  59. * 5-May-2004 Graeme McKerrell
  60. * updates following review
  61. * 2-Mar-2004 Graeme McKerrell
  62. * Fixed to account for comparision logic being (node - key)
  63. * original algorithm expected (key - node)
  64. * 9-Feb-2004 Graeme McKerrell
  65. * updated to use new node,key comparison ordering
  66. * 28-Jan-2004 Graeme McKerrell
  67. * Adapted from original public domain code
  68. *---------------------------------------------------------------
  69. * Copyright (C) 2004 3Com Corporation. All Rights Reserved.
  70. **************************************************************** */
  71. #include "private.h"
  72. /*--------------------------------------------------------- */
  73. lub_bintree_node_t *
  74. lub_bintree_splay (const lub_bintree_t *this,
  75. lub_bintree_node_t *t,
  76. const void *key)
  77. {
  78. /* Simple top down splay, not requiring "key" to be in the tree t. */
  79. /* What it does is described above. */
  80. lub_bintree_node_t N, *leftTreeMax, *rightTreeMin, *y;
  81. int comp;
  82. if (t == NULL)
  83. return t;
  84. N.left = N.right = NULL;
  85. leftTreeMax = rightTreeMin = &N;
  86. for (;;)
  87. {
  88. comp = lub_bintree_compare(this,t,key);
  89. if (comp > 0)
  90. {
  91. if (t->left == NULL)
  92. break;
  93. if (lub_bintree_compare(this,t->left,key) > 0)
  94. {
  95. y = t->left; /* rotate right */
  96. t->left = y->right;
  97. y->right = t;
  98. t = y;
  99. if (t->left == NULL)
  100. break;
  101. }
  102. rightTreeMin->left = t; /* link right */
  103. rightTreeMin = t;
  104. t = t->left;
  105. }
  106. else if (comp < 0)
  107. {
  108. if (t->right == NULL)
  109. break;
  110. if (lub_bintree_compare(this,t->right,key) < 0)
  111. {
  112. y = t->right; /* rotate left */
  113. t->right = y->left;
  114. y->left = t;
  115. t = y;
  116. if (t->right == NULL)
  117. break;
  118. }
  119. leftTreeMax->right = t; /* link left */
  120. leftTreeMax = t;
  121. t = t->right;
  122. }
  123. else
  124. {
  125. break;
  126. }
  127. }
  128. leftTreeMax->right = t->left; /* assemble */
  129. rightTreeMin->left = t->right;
  130. t->left = N.right;
  131. t->right = N.left;
  132. /* return the new root */
  133. return t;
  134. }
  135. /*--------------------------------------------------------- */