001package components.binarytree; 002 003import java.util.Iterator; 004import java.util.NoSuchElementException; 005 006/** 007 * {@code BinaryTree} represented as a recursive data structure, done 008 * "bare-handed", with implementations of primary methods. 009 * 010 * <p> 011 * Execution-time performance of all methods implemented in this class is O(1). 012 * 013 * @param <T> 014 * type of {@code BinaryTree} labels 015 * @mathsubtypes <pre> 016 * TREE_REP is ( 017 * size: integer, 018 * height: integer, 019 * rootLabel: T, 020 * leftSubtree: TREE_REP, 021 * rightSubtree: TREE_REP 022 * ) 023 * </pre> 024 * @mathdefinitions {@code 025 * IS_LEGAL_REP ( 026 * tr: TREE_REP 027 * ): boolean is 028 * 0 <= tr.height <= tr.size <= (2^tr.height - 1) and 029 * (if tr.size > 0 then 030 * tr.size = 1 + tr.leftSubtree.size + tr.rightSubtree.size and 031 * tr.height = 1 + max(tr.leftSubtree.height, tr.rightSubtree.height) and 032 * [tr.rootLabel is not null] and 033 * [tr.leftSubtree is not null] and 034 * [tr.rightSubtree is not null] and 035 * [tr.leftSubtree and tr.rightSubtree are not aliases] and 036 * IS_LEGAL_REP(tr.leftSubtree) and 037 * IS_LEGAL_REP(tr.rightSubtree)) 038 * 039 * ABSTRACT_TREE ( 040 * tr: TREE_REP 041 * ): binary tree of T satisfies 042 * if IS_LEGAL_REP(tr) then 043 * (if tr.size = 0 044 * then ABSTRACT_TREE(tr) = empty_tree 045 * else ABSTRACT_TREE(tr) = 046 * compose(tr.rootLabel, ABSTRACT_TREE(tr.leftSubtree), 047 * ABSTRACT_TREE(tr.rightSubtree))) 048 * } 049 * @convention IS_LEGAL_REP($this) 050 * @correspondence this = ABSTRACT_TREE($this) 051 */ 052public class BinaryTree1<T> extends BinaryTreeSecondary<T> { 053 054 /* 055 * Private members -------------------------------------------------------- 056 */ 057 058 /** 059 * Size of tree. 060 */ 061 private int size; 062 063 /** 064 * Height of tree. 065 */ 066 private int height; 067 068 /** 069 * Root label. 070 */ 071 072 private T rootLabel; 073 074 /** 075 * Left subtree. 076 */ 077 private BinaryTree1<T> leftSubtree; 078 079 /** 080 * Right subtree. 081 */ 082 private BinaryTree1<T> rightSubtree; 083 084 /** 085 * Creator of initial representation. 086 */ 087 private void createNewRep() { 088 this.size = 0; 089 this.height = 0; 090 this.rootLabel = null; 091 this.leftSubtree = null; 092 this.rightSubtree = null; 093 } 094 095 /* 096 * Constructors ----------------------------------------------------------- 097 */ 098 099 /** 100 * No-argument constructor. 101 */ 102 public BinaryTree1() { 103 this.createNewRep(); 104 } 105 106 /* 107 * Standard methods ------------------------------------------------------- 108 */ 109 110 @SuppressWarnings("unchecked") 111 @Override 112 public final BinaryTree<T> newInstance() { 113 try { 114 return this.getClass().getConstructor().newInstance(); 115 } catch (ReflectiveOperationException e) { 116 throw new AssertionError( 117 "Cannot construct object of type " + this.getClass()); 118 } 119 } 120 121 @Override 122 public final void clear() { 123 this.createNewRep(); 124 } 125 126 @Override 127 public final void transferFrom(BinaryTree<T> source) { 128 assert source != null : "Violation of: source is not null"; 129 assert source != this : "Violation of: source is not this"; 130 assert source instanceof BinaryTree1<?> 131 : "Violation of: source is of dynamic type BinaryTree1<?>"; 132 /* 133 * This cast cannot fail since the assert above would have stopped 134 * execution in that case: source must be of dynamic type 135 * BinaryTree1<?>, and the ? must be T or the call would not have 136 * compiled. 137 */ 138 BinaryTree1<T> localSource = (BinaryTree1<T>) source; 139 this.size = localSource.size; 140 this.height = localSource.height; 141 this.rootLabel = localSource.rootLabel; 142 this.leftSubtree = localSource.leftSubtree; 143 this.rightSubtree = localSource.rightSubtree; 144 localSource.createNewRep(); 145 } 146 147 /* 148 * Kernel methods --------------------------------------------------------- 149 */ 150 151 @Override 152 public final void assemble(T root, BinaryTree<T> left, BinaryTree<T> right) { 153 assert root != null : "Violation of: root is not null"; 154 assert left != null : "Violation of: left is not null"; 155 assert right != null : "Violation of: right is not null"; 156 assert left != this : "Violation of: left is not this"; 157 assert right != this : "Violation of: right is not this"; 158 assert left != right : "Violation of: left is not right"; 159 assert left instanceof BinaryTree1<?> : "Violation of: left is a BinaryTree1<?>"; 160 assert right instanceof BinaryTree1<?> 161 : "Violation of: right is a BinaryTree1<?>"; 162 /* 163 * These casts cannot fail since the asserts above would have stopped 164 * execution in that case: both left and right must be of dynamic type 165 * BinaryTree1<?>, and the ? must be T or the call would not have 166 * compiled. 167 */ 168 /* 169 * There's a choice here between treating parameters left and right from 170 * the client or the implementer point of view. Here we chose to use the 171 * implementer point of view because it results in (small) performance 172 * gains. Note that transferFrom is used despite this choice, which is 173 * an apparent violation of the kernel purity rule. We considered the 174 * alternative, to make a private version of transferFrom, and call it 175 * here and from the public transferFrom, and decided it was not worth 176 * doing it in this special case. 177 */ 178 BinaryTree1<T> localLeft = (BinaryTree1<T>) left; 179 BinaryTree1<T> localRight = (BinaryTree1<T>) right; 180 this.size = 1 + localLeft.size + localRight.size; 181 if (localLeft.height > localRight.height) { 182 this.height = 1 + localLeft.height; 183 } else { 184 this.height = 1 + localRight.height; 185 } 186 this.rootLabel = root; 187 if (this.leftSubtree == null) { 188 this.leftSubtree = new BinaryTree1<T>(); 189 } 190 this.leftSubtree.transferFrom(localLeft); 191 if (this.rightSubtree == null) { 192 this.rightSubtree = new BinaryTree1<T>(); 193 } 194 this.rightSubtree.transferFrom(localRight); 195 } 196 197 @Override 198 public final T disassemble(BinaryTree<T> left, BinaryTree<T> right) { 199 assert left != null : "Violation of: left is not null"; 200 assert right != null : "Violation of: right is not null"; 201 assert left != this : "Violation of: left is not this"; 202 assert right != this : "Violation of: right is not this"; 203 assert left != right : "Violation of: left is not right"; 204 assert left instanceof BinaryTree1<?> : "Violation of: left is a BinaryTree1<?>"; 205 assert right instanceof BinaryTree1<?> 206 : "Violation of: right is a BinaryTree1<?>"; 207 assert this.size != 0 : "Violation of: this /= empty_tree"; 208 /* 209 * The casts below cannot fail since the asserts above would have 210 * stopped execution in that case: left and right must be of dynamic 211 * type BinaryTree1<?>, and the ? must be T or the call would not have 212 * compiled. 213 */ 214 T localRootLabel = this.rootLabel; 215 BinaryTree1<T> localLeft = (BinaryTree1<T>) left; 216 BinaryTree1<T> localRight = (BinaryTree1<T>) right; 217 localLeft.transferFrom(this.leftSubtree); 218 localRight.transferFrom(this.rightSubtree); 219 this.createNewRep(); 220 return localRootLabel; 221 } 222 223 @Override 224 public final int size() { 225 return this.size; 226 } 227 228 @Override 229 public final Iterator<T> iterator() { 230 return new BinaryTree1Iterator(); 231 } 232 233 /** 234 * Regions for iterator. 235 */ 236 private enum IteratorRegion { 237 /** 238 * There is no next label. 239 */ 240 NONE, 241 /** 242 * Next label is from the left subtree. 243 */ 244 LEFT, 245 /** 246 * Next label is from the root. 247 */ 248 ROOT, 249 /** 250 * Next label is from the right subtree. 251 */ 252 RIGHT 253 }; 254 255 /** 256 * Implementation of {@code Iterator} interface for {@code BinaryTree1}. 257 */ 258 private final class BinaryTree1Iterator implements Iterator<T> { 259 260 /** 261 * Region of tree from which next label will come. 262 */ 263 private IteratorRegion region; 264 265 /** 266 * Iterator from which next label will come, if region is LEFT or RIGHT; 267 * otherwise null. 268 */ 269 private Iterator<T> operative; 270 271 /** 272 * No-argument constructor. 273 */ 274 private BinaryTree1Iterator() { 275 /* 276 * Iterator cannot start in right subtree, so there is no case for 277 * that. 278 */ 279 if (BinaryTree1.this.size == 0) { 280 this.region = IteratorRegion.NONE; 281 this.operative = null; 282 } else if (BinaryTree1.this.leftSubtree.size > 0) { 283 this.region = IteratorRegion.LEFT; 284 this.operative = BinaryTree1.this.leftSubtree.iterator(); 285 } else { 286 this.region = IteratorRegion.ROOT; 287 this.operative = null; 288 } 289 } 290 291 @Override 292 public boolean hasNext() { 293 return this.region != IteratorRegion.NONE; 294 } 295 296 @Override 297 public T next() { 298 assert this.hasNext() : "Violation of: ~this.unseen /= <>"; 299 if (!this.hasNext()) { 300 /* 301 * Exception is supposed to be thrown in this case, but with 302 * assertion-checking enabled it cannot happen because of assert 303 * above. 304 */ 305 throw new NoSuchElementException(); 306 } 307 T result = null; 308 switch (this.region) { 309 case NONE: { 310 /* 311 * Cannot happen because of code above. 312 */ 313 throw new AssertionError("Unreachable branch."); 314 } 315 case LEFT: { 316 result = this.operative.next(); 317 if (!this.operative.hasNext()) { 318 this.region = IteratorRegion.ROOT; 319 this.operative = null; 320 } 321 break; 322 } 323 case ROOT: { 324 result = BinaryTree1.this.rootLabel; 325 if (BinaryTree1.this.rightSubtree.size > 0) { 326 this.region = IteratorRegion.RIGHT; 327 this.operative = BinaryTree1.this.rightSubtree.iterator(); 328 } else { 329 this.region = IteratorRegion.NONE; 330 this.operative = null; 331 } 332 break; 333 } 334 case RIGHT: { 335 result = this.operative.next(); 336 if (!this.operative.hasNext()) { 337 this.region = IteratorRegion.NONE; 338 this.operative = null; 339 } 340 break; 341 } 342 default: { 343 /* 344 * Cannot happen because of the type of the expression. 345 */ 346 throw new AssertionError("Unreachable branch."); 347 } 348 } 349 return result; 350 } 351 352 @Override 353 public void remove() { 354 throw new UnsupportedOperationException("remove operation not supported"); 355 } 356 357 } 358 359 /* 360 * Other methods (overridden for performance reasons) --------------------- 361 */ 362 363 @Override 364 public final T root() { 365 assert this.size != 0 : "Violation of: this /= empty_tree"; 366 return this.rootLabel; 367 } 368 369 @Override 370 public final T replaceRoot(T x) { 371 assert this.size != 0 : "Violation of: this /= empty_tree"; 372 T root = this.rootLabel; 373 this.rootLabel = x; 374 return root; 375 } 376 377 @Override 378 public final int height() { 379 return this.height; 380 } 381 382}