Advertisement
Guest User

Untitled

a guest
Jun 19th, 2016
54
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.26 KB | None | 0 0
  1. public class BaumAVL<T extends Comparable<T>> {
  2. private class Knoten {
  3. private Knoten l; // linker Teilbaum
  4. private Knoten r; // rechter Teilbaum
  5. private int b; // hoehe(linker TB) - hoehe(rechter TB)
  6. private T e; // Wert am Knoten
  7. public Knoten(T e) { this.e = e; }
  8. }
  9. private Knoten w; // Wurzel
  10.  
  11. public boolean isEmpty() {
  12. return w == null;
  13. }
  14.  
  15. public T element() {
  16. if (isEmpty()) {
  17. throw new java.util.NoSuchElementException();
  18. }
  19. return w.e;
  20. }
  21.  
  22. public boolean contains(T e) {
  23. Knoten k = w;
  24. while (k != null) {
  25. int c = k.e.compareTo(e);
  26. if (c == 0) { // Element gefunden
  27. return true;
  28. }
  29. else if (c > 0) { // falls k.e > e,
  30. k = k.l; // dann e im linken Teilbaum
  31. }
  32. else { // falls k.e < e,
  33. k = k.r; // dann e im rechten Teilbaum
  34. }
  35. }
  36. return false;
  37. }
  38.  
  39. public boolean add(T e) {
  40. return add(w, null, false, e) >= 0;
  41. }
  42.  
  43. /**
  44. * rekursives Einfuegen in einen Teilbaum
  45. * @k der Wurzelknoten des Baumes bzw. Teilbaums, in den eingefuegt wird
  46. * @m Mutterknoten von k, k ist linkes oder rechtes Kind von m
  47. * @istLinks gibt an, ob k das linke Kind der Mutter ist - sonst oder fuer Wurzel: false
  48. * @e der einzufuegende Wert
  49. * @return -1, falls Element bereits vorhanden; 1, falls der Teilbaum durch das Einfuegen hoeher
  50. * geworden ist; 0 sonst
  51. */
  52. private int add(Knoten k, Knoten m, boolean istLinks, T e) {
  53. if (k == null) { // an leerem Teilbaum angekommen
  54. k = new Knoten(e); // dann wird hier ein neuer Knoten erzeugt
  55. if (m == null) { // nur moeglich, wenn w==null, also Baum leer
  56. w = k; // dann besteht der Baum jetzt aus genau einem Knoten
  57. } // ansonsten muessen wir untersuchen, ob der neue Knoten
  58. else if (istLinks) { // linkes oder rechtes Kind seiner Mutter wird.
  59. m.l = k;
  60. }
  61. else {
  62. m.r = k;
  63. }
  64. return 1; // Teilbaum mit k als Wurzel ist gewachsen
  65. }
  66.  
  67. // Wenn wir hier angekommen sind, gilt k != null.
  68.  
  69. int c = k.e.compareTo(e);
  70. if (c == 0) { // Wert e schon im Baum vorhanden
  71. return -1; // kein Einfuegen, keine Hoehenaenderung
  72. }
  73. else if (c > 0) { // k.e > e => in linken Teilbaum einfuegen
  74. int r = add(k.l, k, true, e);
  75. if (r == 1) { // Wenn sich die Hoehe des Teilbaums aendert,
  76. k.b++; // erhoeht sich der balance-Wert von k.
  77. }
  78. else { // sonst keine Einfuegung bzw. keine Hoehenaenderung
  79. return r; // im Teilbaum (kein Ausgleich bei k noetig)
  80. }
  81. }
  82. else { // k.e < e => in rechten Teilbaum einfuegen
  83. int r = add(k.r, k, false, e);
  84. if (r == 1) { // Wenn sich die Hoehe des Teilbaums aendert,
  85. k.b--; // verringert sich der balance-Wert von k.
  86. }
  87. else { // sonst keine Einfuegung bzw. keine Hoehenaenderung
  88. return r; // im Teilbaum (kein Ausgleich bei k noetig)
  89. }
  90. }
  91.  
  92. // Die Hoehe des Teilbaumes, in den eingefuegt wurde, ist gewachsen.
  93.  
  94. if (k.b == 0) { // Baum balanciert => Fall 2
  95. return 0; // Hoehe des Baumes mit Wurzel k ist gleich geblieben
  96. }
  97.  
  98. if (k.b == 1 || k.b == -1) { // AVL Kriterium noch erfuellt => Fall 1
  99. return 1; // Hoehe des Baumes mit Wurzel k ist gewachsen
  100. }
  101.  
  102. // Wenn wir hier angekommen sind, ist die Hoehe des Baumes mit k als Wurzel erhoeht,
  103. // und das AVL-Kriterium ist verletzt => Fall 3
  104.  
  105. if (k.b == 2) { // der linke Teilbaum ist hoeher als der rechte
  106. if (k.l.b == 1) {
  107. rotateLL(k, m); // Fall 3a
  108. }
  109. else if (k.l.b == -1) {
  110. rotateLR(k, m); // Fall 3b
  111. }
  112. else {
  113. assert false : "Illegaler Zustand im AVL-Baum";
  114. }
  115. }
  116. else if (k.b == -2) { // der rechte Teilbaum ist hoeher als der linke
  117. if (k.r.b == -1) {
  118. rotateRR(k, m); // Fall symmetrisch zu 3a
  119. }
  120. else if (k.r.b == 1) {
  121. rotateRL(k, m); // Fall symmetrisch zu 3b
  122. }
  123. else {
  124. assert false : "Illegaler Zustand im AVL-Baum";
  125. }
  126. }
  127. else {
  128. assert false : "Illegaler Zustand im AVL-Baum";
  129. }
  130.  
  131. // Ausgleichsrotationen fuehren beim Einfuegen stets dazu, dass der Teilbaum mit
  132. // k als Wurzel nicht gewachsen ist.
  133. return 0;
  134. }
  135.  
  136. public boolean remove(T e) {
  137. return remove(w, null, false, null, e) >= 0;
  138. }
  139.  
  140. /**
  141. * rekursives Entfernen aus einem Teilbaum
  142. * @k der Wurzelknoten des Baumes bzw. Teilbaums, aus dem entfernt wird
  143. * @m Mutterknoten von k, k ist linkes oder rechtes Kind von m
  144. * @istLinks gibt an, ob k das linke Kind der Mutter ist - sonst oder fuer Wurzel: false
  145. * @kAlt zu entfernender innerer Knoten (in Fall (c) des Entfernens aus einem Suchbaum)
  146. * @e der zu entfernende Wert
  147. * @return -1, falls Element nicht vorhanden; 1, falls der Teilbaum durch das Entfernen niedriger
  148. * geworden ist; 0 sonst
  149. */
  150. private int remove(Knoten k, Knoten m, boolean istLinks, Knoten kAlt, T e) {
  151. if (k == null) { // an leerem Teilbaum angekommen
  152. return -1; // Element nicht vorhanden: fertig, keine Hoehenaenderung
  153. }
  154.  
  155. // Wenn wir hier angekommen sind, gilt k != null.
  156.  
  157. if (kAlt != null) { // zum Ersetzen groesstes Element des Teilbaums loeschen
  158. if (k.r == null) { // k enthaelt groesstes Element, wird entfernt
  159. // k ist Blatt oder hat links Blatt als Kind
  160. kAlt.e = k.e; // ueberschreibe zu loeschenden Wert
  161. // m ist nicht null, da wir im linken Teilbaum von kAlt sind
  162. if (m == kAlt) {
  163. m.l = k.l; // k ist linkes Kind von kAlt
  164. }
  165. else {
  166. m.r = k.l; // k liegt auf rechtem Pfad im linken Teilbaum
  167. }
  168. return 1; // Hoehe des Teilbaums hat sich geaendert
  169. }
  170. else { // suche weiter nach groesstem Element
  171. int r = remove(k.r, k, false, kAlt, null);
  172. if (r == 1) { // aendert sich Hoehe des Teilbaums,
  173. // <hier Code einfuegen>
  174. }
  175. else {
  176. return r; // Element nicht vorhanden oder Hoehe ist gleich geblieben
  177. }
  178. }
  179. }
  180. else { // e suchen und entfernen
  181. int c = k.e.compareTo(e);
  182. if (c == 0) { // Wert e gefunden
  183. if (k.l == null || k.r == null) { // k ist Blatt oder hat nur 1 Kind
  184. Knoten kind = (k.l == null) ? k.r : k.l;
  185. if (m == null) { // k ist w
  186. w = kind;
  187. }
  188. else { // k hat Mutter
  189. if (istLinks) {
  190. m.l = kind;
  191. }
  192. else {
  193. m.r = kind;
  194. }
  195. }
  196. return 1; // Hoehe des Teilbaums hat sich geaendert
  197. }
  198. else { // k hat 2 Teilbaeume => Fall (c)
  199. // entferne den groessten Wert im linken Teilbaum
  200. // Verbesserungsmoeglichkeit: entferne kleinsten Wert im rechten, falls dieser hoeher ist
  201. int r = remove(k.l, k, true, k, null);
  202. if (r == 1) { // aendert sich Hoehe des Teilbaums,
  203. k.b--; // verringert sich der balance-Wert von k.
  204. }
  205. else {
  206. return r; // Hoehe des Baumes mit Wurzel k ist gleich geblieben
  207. }
  208. }
  209. }
  210. else if (c > 0) { // k.e > e => aus linkem Teilbaum entfernen
  211. int r = remove(k.l, k, true, null, e);
  212. if (r == 1) { // Wenn sich die Hoehe des Teilbaums aendert,
  213. k.b--; // verringert sich der balance-Wert von k.
  214. }
  215. else {
  216. return r; // Hoehe des Baumes mit Wurzel k ist gleich geblieben
  217. }
  218. }
  219. else { // k.e < e => aus rechtem Teilbaum entfernen
  220. // <hier Code einfuegen>
  221. }
  222. }
  223.  
  224. // Die Hoehe des Teilbaumes, aus dem entfernt wurde, hat sich verringert.
  225.  
  226. if (k.b == 0) { // Baum balanciert => Fall 2
  227. // <hier Code einfuegen>
  228. }
  229.  
  230. if (k.b == 1 || k.b == -1) { // AVL Kriterium noch erfuellt => Fall 1
  231. // <hier Code einfuegen>
  232. }
  233.  
  234. // Das AVL-Kriterium ist verletzt => Fall 3
  235.  
  236. // Fall 3a/b/c
  237. if (k.b == 2) { // der linke Teilbaum ist hoeher als der rechte
  238. if (k.l.b == 1) {
  239. rotateLL(k, m); // Fall 3a
  240. }
  241. else if (k.l.b == -1) {
  242. rotateLR(k, m); // Fall 3b
  243. }
  244. else if (k.l.b == 0) {
  245. rotateLL(k, m); // Fall 3c
  246. return 0; // keine Hoehenaenderung fuer Teilbaum mit Wurzel k
  247. }
  248. else {
  249. assert false : "Illegaler Zustand im AVL-Baum";
  250. }
  251. }
  252. else if (k.b == -2) { // der rechte Teilbaum ist hoeher als der linke
  253. // <hier Code einfuegen>
  254. }
  255. else {
  256. assert false : "Illegaler Zustand im AVL-Baum";
  257. }
  258.  
  259. // Ausgleichsrotationen (ausser fuer Fall 3c) fuehren beim Entfernen stets dazu, dass sich die
  260. // Hoehe des Teilbaum mit k als Wurzel verringert.
  261. return 1;
  262. }
  263.  
  264. private void rotateLL(Knoten k, Knoten m) { // Fall 3a/c
  265. Knoten v = k.l;
  266. Knoten a1 = v.l;
  267. Knoten a2 = v.r;
  268. Knoten b = k.r;
  269.  
  270. if (m == null) { // wenn Rotation an Wurzel
  271. w = v; // dann haben wir jetzt eine neue Wurzel
  272. } else if (k == m.l) { // ansonsten hat m ein neues linkes oder rechtes Kind
  273. m.l = v;
  274. } else {
  275. m.r = v;
  276. }
  277.  
  278. // Verweise umhaengen
  279. v.r = k;
  280. v.l = a1;
  281. k.l = a2;
  282. k.r = b;
  283.  
  284. if (v.b == 1) { // Fall 3a
  285. v.b = 0; // beide Teilbaeume sind jetzt ausgeglichen
  286. k.b = 0;
  287. }
  288. else if (v.b == 0) { // Fall 3c
  289. v.b = -1;
  290. k.b = 1;
  291. }
  292. else {
  293. assert false : "Illegaler Zustand im AVL-Baum";
  294. }
  295. }
  296. //TEILAUFGABE ANFANG
  297. private void rotateRR(Knoten k, Knoten m) { // symmetrisch zu Fall 3a/c
  298. Knoten v = k.r;
  299. Knoten a1 = k.l;
  300. Knoten a2 = v.l;
  301. Knoten b = v.r;
  302.  
  303. if (m == null) { // wenn Rotation an Wurzel
  304. w = v; // dann haben wir jetzt eine neue Wurzel
  305. } else if (k == m.r) { // ansonsten hat m ein neues linkes oder rechtes Kind
  306. m.r = v;
  307. } else {
  308. m.l = v;
  309. }
  310.  
  311. // Verweise umhaengen
  312. v.l = k;
  313. v.r = b;
  314. k.r = a2;
  315. k.l = a1;
  316.  
  317. if (v.b == 1) { // Fall 3a
  318. v.b = 0; // beide Teilbaeume sind jetzt ausgeglichen
  319. k.b = 0;
  320. }
  321. else if (v.b == 0) { // Fall 3c
  322. v.b = -1;
  323. k.b = 1;
  324. }
  325. else {
  326. assert false : "Illegaler Zustand im AVL-Baum";
  327. }
  328. }
  329. //TEILAUFGABE ENDE
  330. private void rotateLR(Knoten k, Knoten m) { // Fall 3b
  331. Knoten v = k.l;
  332. Knoten u = v.r;
  333. Knoten a1 = v.l;
  334. Knoten a2 = u.l;
  335. Knoten a3 = u.r;
  336. Knoten b = k.r;
  337. int bAlt = u.b; // alte balance von u sichern, da u sich aendert
  338.  
  339. if (m == null) { // wenn Rotation an Wurzel
  340. w = u; // dann haben wir jetzt eine neue Wurzel
  341. } else if (k == m.l) { // ansonsten hat m ein neues linkes oder rechtes Kind
  342. m.l = u;
  343. } else {
  344. m.r = u;
  345. }
  346.  
  347. u.l = v;
  348. u.r = k;
  349. v.l = a1;
  350. v.r = a2;
  351. k.l = a3;
  352. k.r = b;
  353.  
  354. switch (bAlt)
  355. {
  356. case 0 : // hoehe(A2)=hoehe(A3)=h-1
  357. v.b = 0;
  358. k.b = 0;
  359. break;
  360. case 1 : // hoehe(A2)=h-1, hoehe(A3)=h-2
  361. v.b = 0;
  362. k.b = -1;
  363. break;
  364. case -1 : // hoehe(A2)=h-2, hoehe(A3)=h-1
  365. v.b = 1;
  366. k.b = 0;
  367. break;
  368. }
  369. u.b = 0;
  370. }
  371. //TEILAUFGABE ANFANG
  372. private void rotateRL(Knoten k, Knoten m) { // symmetrisch zu Fall 3b
  373. Knoten v = k.r;
  374. Knoten u = v.l;
  375. Knoten a1 = v.r;
  376. Knoten a2 = u.r;
  377. Knoten a3 = u.l;
  378. Knoten b = k.l;
  379. int bAlt = u.b; // alte balance von u sichern, da u sich aendert
  380.  
  381. if (m == null) { // wenn Rotation an Wurzel
  382. w = u; // dann haben wir jetzt eine neue Wurzel
  383. } else if (k == m.r) { // ansonsten hat m ein neues linkes oder rechtes Kind
  384. m.r = u;
  385. } else {
  386. m.l = u;
  387. }
  388.  
  389. u.r = v;
  390. u.l = k;
  391. v.r = a1;
  392. v.l = a2;
  393. k.r = a3;
  394. k.l = b;
  395.  
  396. switch (bAlt)
  397. {
  398. case 0 : // hoehe(A2)=hoehe(A3)=h-1
  399. v.b = 0;
  400. k.b = 0;
  401. break;
  402. case 1 : // hoehe(A2)=h-1, hoehe(A3)=h-2
  403. v.b = 0;
  404. k.b = -1;
  405. break;
  406. case -1 : // hoehe(A2)=h-2, hoehe(A3)=h-1
  407. v.b = 1;
  408. k.b = 0;
  409. break;
  410. }
  411. u.b = 0;
  412. }
  413. public String toString(){
  414. return toString(w);
  415. }
  416. private String toString(Knoten k){
  417. if (k==null)
  418. return "()";
  419. return "("+ toString(k.l) + k.e + toString(k.r) +")";
  420. }
  421. }
  422. //FERTIG
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement