├── .gitignore ├── .idea ├── vcs.xml └── workspace.xml ├── README.md ├── fxbinarytree.iml ├── pom.xml ├── src └── main │ ├── java │ ├── app │ │ └── Main.java │ ├── controller │ │ ├── GraphicsController.java │ │ └── GraphicsTree.java │ ├── shape │ │ ├── Circle.java │ │ └── Line.java │ └── tree │ │ ├── BinarySearchTree.java │ │ ├── BinaryTreeBasis.java │ │ ├── QueueException.java │ │ ├── TreeException.java │ │ ├── TreeIterator.java │ │ └── TreeNode.java │ └── resources │ ├── fxml │ └── FXMLGraphicsPanel.fxml │ ├── image │ └── binarytree_screenshot.png │ └── style │ └── graphics_controller.css └── target └── classes ├── app └── Main.class ├── controller ├── GraphicsController.class └── GraphicsTree.class ├── fxml └── FXMLGraphicsPanel.fxml ├── shape ├── Circle.class └── Line.class ├── style └── graphics_controller.css └── tree ├── BinarySearchTree.class ├── BinaryTreeBasis.class ├── QueueException.class ├── TreeException.class ├── TreeIterator.class └── TreeNode.class /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Example user template template 3 | ### Example user template 4 | 5 | # IntelliJ project files 6 | .idea 7 | *.iml 8 | out 9 | gen 10 | .gitignore 11 | src/test/ 12 | target/classes/image/ 13 | target/generated-sources/ 14 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 132 | 133 | 136 | 137 | 138 | 159 | 160 | 161 | 162 | 163 | true 164 | DEFINITION_ORDER 165 | 166 | 167 | 172 | 173 | 174 | 175 | 176 | 177 | 180 | 181 | 184 | 185 | 186 | 187 | 188 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 215 | 216 | 219 | 220 | 221 | 222 | 225 | 226 | 229 | 230 | 233 | 234 | 235 | 236 | 239 | 240 | 243 | 244 | 247 | 248 | 251 | 252 | 253 | 254 | 257 | 258 | 261 | 262 | 265 | 266 | 269 | 270 | 273 | 274 | 275 | 276 | 279 | 280 | 283 | 284 | 287 | 288 | 291 | 292 | 295 | 296 | 299 | 300 | 301 | 302 | 305 | 306 | 309 | 310 | 313 | 314 | 317 | 318 | 321 | 322 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 359 | 360 | 361 | 362 | 363 | 376 | 377 | 378 | 383 | 384 | 385 | 411 | 412 | 413 | 438 | 439 | 446 | 447 | 448 | 461 | 462 | 463 | 464 | 469 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 495 | 513 | 520 | 521 | 522 | 523 | 524 | 525 | 542 | 543 | 564 | 577 | 578 | 587 | 591 | 592 | 593 | 600 | 603 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 687 | 688 | 689 | 699 | 700 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 734 | 741 | 742 | project 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 771 | 772 | 773 | 775 | 776 | 777 | 778 | 1499366758985 779 | 793 | 794 | 795 | 796 | 798 | 799 | 800 | 801 | 802 | 803 | 804 | 805 | 806 | 807 | 808 | 809 | 810 | 811 | 812 | 813 | 814 | 815 | 816 | 817 | 818 | 819 | 820 | 821 | 822 | 823 | 824 | 825 | 826 | 827 | 828 | 829 | 830 | 831 | 832 | 833 | 834 | 835 | 837 | 838 | 840 | 841 | 842 | 843 | 844 | file://$PROJECT_DIR$/src/main/java/tree/BinaryTreeBasis.java 845 | 19 846 | 847 | 848 | 849 | 851 | 852 | 853 | 854 | 857 | 858 | 859 | 860 | 861 | 862 | 863 | 864 | 865 | 866 | 867 | 868 | 869 | 870 | 871 | 872 | 873 | 874 | 875 | 876 | 877 | 878 | 879 | 880 | 881 | 882 | 883 | 884 | 885 | 886 | 887 | 888 | 889 | 890 | 891 | 892 | 893 | 894 | 895 | 896 | 897 | 898 | 899 | 900 | 901 | 902 | 903 | 904 | 905 | 906 | 907 | 908 | 909 | 910 | 911 | 912 | 913 | 914 | 915 | 916 | 917 | 918 | 919 | 920 | 921 | 922 | 923 | 924 | 925 | 926 | 927 | 928 | 929 | 930 | 931 | 932 | 933 | 934 | 935 | 936 | 937 | 938 | 939 | 940 | 941 | 942 | 943 | 944 | 945 | 946 | 947 | 948 | 949 | 950 | 951 | 952 | 953 | 954 | 955 | 956 | 957 | 958 | 959 | 960 | 961 | 962 | 963 | 964 | 965 | 966 | 967 | 968 | 969 | 970 | 971 | 972 | 973 | 974 | 975 | 976 | 977 | 978 | 979 | 980 | 981 | 982 | 983 | 984 | 985 | 986 | 987 | 988 | 989 | 990 | 991 | 992 | 993 | 994 | 995 | 996 | 997 | 998 | 999 | 1000 | 1001 | 1002 | 1003 | 1004 | 1005 | 1006 | 1007 | 1008 | 1009 | 1010 | 1011 | 1012 | 1013 | 1014 | 1015 | 1016 | 1017 | 1018 | 1019 | 1020 | 1021 | 1022 | 1023 | 1024 | 1025 | 1026 | 1027 | 1028 | 1029 | 1030 | 1031 | 1032 | 1033 | 1034 | 1035 | 1036 | 1037 | 1038 | 1039 | 1040 | 1041 | 1042 | 1043 | 1044 | 1045 | 1046 | 1047 | 1048 | 1049 | 1050 | 1051 | 1052 | 1053 | 1054 | 1055 | 1056 | 1057 | 1058 | 1059 | 1060 | 1061 | 1062 | 1063 | 1064 | 1065 | 1066 | 1067 | 1068 | 1069 | 1070 | 1071 | 1072 | 1073 | 1074 | 1075 | 1076 | 1077 | 1078 | 1079 | 1080 | 1081 | 1082 | 1083 | 1084 | 1085 | 1086 | 1087 | 1088 | 1089 | 1090 | 1091 | 1092 | 1093 | 1094 | 1095 | 1096 | 1097 | 1098 | 1099 | 1100 | 1101 | 1102 | 1103 | 1104 | 1105 | 1106 | 1107 | 1108 | 1109 | 1110 | 1111 | 1112 | 1113 | 1114 | 1115 | 1116 | 1117 | 1118 | 1119 | 1120 | 1121 | 1122 | 1123 | 1124 | 1125 | 1126 | 1127 | 1128 | 1129 | 1130 | 1131 | 1132 | 1133 | 1134 | 1135 | 1136 | 1137 | 1138 | 1139 | 1140 | 1141 | 1142 | 1143 | 1144 | 1145 | 1146 | 1147 | 1148 | 1149 | 1150 | 1151 | 1152 | 1153 | 1154 | 1155 | 1156 | 1157 | 1158 | 1159 | 1160 | 1161 | 1162 | 1163 | 1164 | 1165 | 1166 | 1167 | 1168 | 1169 | 1170 | 1171 | 1172 | 1173 | 1174 | 1175 | 1176 | 1177 | 1178 | 1179 | 1180 | 1181 | 1182 | 1183 | 1184 | 1185 | 1186 | 1187 | 1188 | 1189 | 1190 | 1191 | 1192 | 1193 | 1194 | 1195 | 1196 | 1197 | 1198 | 1199 | 1200 | 1201 | 1202 | 1203 | 1204 | 1205 | 1206 | 1207 | 1208 | 1209 | 1210 | 1211 | 1212 | 1213 | 1214 | 1215 | 1216 | 1217 | 1218 | 1219 | 1220 | 1221 | 1222 | 1223 | 1224 | 1225 | 1226 | 1227 | 1228 | 1229 | 1230 | 1231 | 1232 | 1233 | 1234 | 1235 | 1236 | 1237 | 1238 | 1239 | 1240 | 1241 | 1242 | 1243 | 1244 | 1245 | 1246 | 1247 | 1248 | 1249 | 1250 | 1251 | 1252 | 1253 | 1254 | 1255 | 1256 | 1257 | 1258 | 1259 | 1260 | 1261 | 1262 | 1263 | 1264 | 1265 | 1266 | 1267 | 1268 | 1269 | 1270 | 1271 | 1272 | 1273 | 1274 | 1275 | 1276 | 1277 | 1278 | 1279 | 1280 | 1281 | 1282 | 1283 | 1284 | 1285 | 1286 | 1287 | 1288 | 1289 | 1290 | 1291 | 1292 | 1293 | 1294 | 1295 | 1296 | 1297 | 1298 | 1299 | 1300 | 1301 | 1302 | 1303 | 1304 | 1305 | 1306 | 1307 | 1308 | 1309 | 1310 | 1311 | 1312 | 1313 | 1314 | 1315 | 1316 | 1317 | 1318 | 1319 | 1320 | 1321 | 1322 | 1323 | 1324 | 1325 | 1326 | 1327 | 1328 | 1329 | 1330 | 1331 | 1332 | 1333 | 1334 | 1335 | 1336 | 1337 | 1338 | 1339 | 1340 | 1341 | 1342 | 1343 | 1344 | 1345 | 1346 | 1347 | 1348 | 1349 | 1350 | 1351 | 1352 | 1353 | 1354 | 1355 | 1356 | 1357 | 1358 | 1359 | 1360 | 1361 | 1362 | 1363 | 1364 | 1365 | 1366 | 1367 | 1368 | 1369 | 1370 | 1371 | 1372 | 1373 | 1378 | 1379 | 1380 | 1381 | 1382 | 1383 | No facets are configured 1384 | 1385 | 1390 | 1391 | 1392 | 1393 | 1394 | 1395 | 1396 | 1401 | 1402 | 1403 | 1404 | 1405 | 1406 | 1.8 1407 | 1408 | 1413 | 1414 | 1415 | 1416 | 1417 | 1418 | fxbinarytree 1419 | 1420 | 1426 | 1427 | 1428 | 1429 | 1430 | 1431 | 1.8 1432 | 1433 | 1438 | 1439 | 1440 | 1441 | 1442 | 1443 | 1444 | 1449 | 1450 | 1451 | 1452 | 1453 | 1454 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FXBinaryTree 2 | 3 | Elegant javafx binary tree demo. 4 | 5 | ### Screenshot 6 | ![alt text](https://github.com/EricCanull/fxbinarytree/blob/master/src/main/resources/image/binarytree_screenshot.png "Binary Tree") 7 | -------------------------------------------------------------------------------- /fxbinarytree.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | fxbinarytree 8 | fxbinarytree 9 | 1.0-SNAPSHOT 10 | 11 | 12 | 13 | org.apache.maven.plugins 14 | maven-compiler-plugin 15 | 16 | 1.8 17 | 1.8 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/main/java/app/Main.java: -------------------------------------------------------------------------------- 1 | package app; 2 | 3 | import javafx.application.Application; 4 | import javafx.fxml.FXMLLoader; 5 | import javafx.scene.Parent; 6 | import javafx.scene.Scene; 7 | import javafx.stage.Stage; 8 | 9 | /** 10 | * Demonstrates a Binary Search Tree using javafx components. 11 | * @author Eric Canull 12 | * @version 1.0 13 | */ 14 | public class Main extends Application { 15 | 16 | /** 17 | * Builds the Graphic UI. 18 | */ 19 | @Override 20 | public void start(Stage stage) throws Exception { 21 | Parent root = FXMLLoader.load(getClass().getResource("/fxml/FXMLGraphicsPanel.fxml")); 22 | 23 | Scene scene = new Scene(root); 24 | 25 | stage.setScene(scene); 26 | stage.show(); 27 | } 28 | 29 | /** 30 | * @param args the command line arguments 31 | */ 32 | public static void main(String... args) { 33 | launch(args); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/controller/GraphicsController.java: -------------------------------------------------------------------------------- 1 | package controller; 2 | 3 | import javafx.event.ActionEvent; 4 | import javafx.fxml.FXML; 5 | import javafx.fxml.Initializable; 6 | import javafx.scene.control.*; 7 | import javafx.scene.layout.BorderPane; 8 | 9 | import java.net.URL; 10 | import java.util.ResourceBundle; 11 | 12 | /** 13 | * Constructs the GUI components and performs events for displaying and 14 | * manipulating the binary tree. 15 | * @author Eric Canull 16 | * @version 1.0 17 | */ 18 | public final class GraphicsController implements Initializable { 19 | 20 | // Panels and other GUI components 21 | @FXML private BorderPane root_container; 22 | @FXML private TextArea traversal_textarea; 23 | @FXML private TextField input_field; 24 | 25 | private GraphicsTree graphicsTree; 26 | 27 | /** 28 | * Constructs the GUI components and performs events for displaying and 29 | * changing the data in the binary tree. 30 | */ 31 | @Override 32 | public void initialize(URL location, ResourceBundle resources) { 33 | 34 | // The center panel for drawing the tree 35 | graphicsTree = new GraphicsTree(); 36 | // Add the panels onto the border pane 37 | root_container.setCenter(graphicsTree); 38 | 39 | // Bind canvas size to stack pane size. 40 | graphicsTree.widthProperty().bind(root_container.widthProperty()); 41 | graphicsTree.heightProperty().bind(root_container.heightProperty().subtract(50)); 42 | } 43 | 44 | /** 45 | * Performs the action when the search button is clicked. 46 | */ 47 | @FXML private void searchOnAction(ActionEvent event) { 48 | try { 49 | graphicsTree.search(Integer.parseInt(input_field.getText().trim())); 50 | } catch (NumberFormatException nfe) { 51 | Alert alert = new Alert(Alert.AlertType.ERROR, 52 | "Error searching for value. The input field can only accept numbers.", ButtonType.OK); 53 | 54 | alert.showAndWait() 55 | .filter(response -> response == ButtonType.OK) 56 | .ifPresent(response -> alert.close()); 57 | 58 | } 59 | } 60 | 61 | /** 62 | * Performs the action when the delete button is clicked. 63 | */ 64 | @FXML private void deleteOnAction(ActionEvent event) { 65 | try { 66 | graphicsTree.delete(Integer.parseInt(input_field.getText().trim())); 67 | } catch (NumberFormatException nfe) { 68 | Alert alert = new Alert(Alert.AlertType.ERROR, "Error deleting value. The input field can only accept numbers.", 69 | ButtonType.OK); 70 | alert.showAndWait() 71 | .filter(response -> response == ButtonType.OK) 72 | .ifPresent(response -> alert.close()); 73 | } 74 | } 75 | 76 | private void clearTree() { 77 | graphicsTree.makeEmpty(); 78 | traversal_textarea.setText(""); 79 | } 80 | /** 81 | * Performs the action when the clear button is clicked. 82 | */ 83 | @FXML private void clearOnAction(ActionEvent event) { 84 | Alert alert = new Alert(Alert.AlertType.CONFIRMATION, "Do you want to empty the tree?", ButtonType.OK); 85 | alert.showAndWait() 86 | .filter(response -> response == ButtonType.OK) 87 | .ifPresent(response -> clearTree()); 88 | 89 | } 90 | 91 | /** 92 | * Performs the action when the insert button is clicked. 93 | */ 94 | @FXML private void insertOnAction(ActionEvent event) { 95 | try { 96 | graphicsTree.insert(Integer.parseInt(input_field.getText().trim())); 97 | } catch (NumberFormatException nfe) { 98 | Alert alert = new Alert(Alert.AlertType.ERROR, "Error inserting value. The input field can only accept numbers.", 99 | ButtonType.OK); 100 | alert.showAndWait() 101 | .filter(response -> response == ButtonType.OK) 102 | .ifPresent(response -> alert.close()); 103 | } 104 | } 105 | 106 | /** 107 | * Performs the action when the first traversal button is clicked. 108 | */ 109 | @FXML private void inorderOnAction(ActionEvent event) { 110 | graphicsTree.setInorder(); 111 | traversal_textarea.setText(graphicsTree.printTree()); 112 | } 113 | 114 | /** 115 | * Performs the action when the second traversal button is clicked. 116 | */ 117 | @FXML private void preorderOnAction(ActionEvent event) { 118 | graphicsTree.setPreorder(); 119 | traversal_textarea.setText(graphicsTree.printTree()); 120 | } 121 | 122 | /** 123 | * Performs the action when the third traversal button is clicked. 124 | */ 125 | @FXML private void postorderOnAction(ActionEvent event) { 126 | graphicsTree.setPostorder(); 127 | traversal_textarea.setText(graphicsTree.printTree()); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/main/java/controller/GraphicsTree.java: -------------------------------------------------------------------------------- 1 | package controller; 2 | 3 | import javafx.geometry.Point2D; 4 | import javafx.scene.canvas.Canvas; 5 | import javafx.scene.canvas.GraphicsContext; 6 | import javafx.scene.control.Alert; 7 | import javafx.scene.control.ButtonType; 8 | 9 | import tree.*; 10 | import shape.*; 11 | import java.util.Objects; 12 | 13 | /** 14 | * Draws the tree and updates the graphics to display according to the 15 | * searching, inserting, deleting, and traversal options. 16 | * @author Eric Canull 17 | * @version 1.0 18 | */ 19 | @SuppressWarnings("serial") 20 | public final class GraphicsTree extends Canvas { 21 | 22 | /** 23 | * The initial input values for the tree. 24 | */ 25 | private static final Integer[] NUMBERS_ARRAY = { 50, 25, 30, 12, 10, 75, 70, 80, 110 }; 26 | 27 | private BinarySearchTree tree; // The BST 28 | private TreeIterator treeIterator; // The BST Iterator 29 | private Circle insertCircle; // Insert circle 30 | private int maxTreeHeight; // Max tree height; 31 | 32 | /** 33 | * Draws the tree and updates the graphics to display according to the 34 | * searching, inserting, deleting, and traversal options. 35 | */ 36 | public GraphicsTree() { 37 | 38 | widthProperty().addListener(evt -> drawTree()); 39 | heightProperty().addListener(evt -> drawTree()); 40 | 41 | createTree(); 42 | } 43 | 44 | /** 45 | * Changes the tree rendered by this panel. 46 | */ 47 | public void setTree(BinarySearchTree root) { tree = root; } 48 | 49 | /** 50 | * Creates the initial binary search tree with the default values 51 | * in the numbers array. 52 | */ 53 | public void createTree() { 54 | 55 | tree = new BinarySearchTree(); // Create an empty tree 56 | setMaxTreeHeight(7); // Set the default max tree height 57 | 58 | for (Integer number : NUMBERS_ARRAY) { 59 | Circle circle = new Circle(number); 60 | tree.insertItem(circle); 61 | } 62 | 63 | drawTree(); 64 | } 65 | 66 | /** 67 | * Set the max tree height. 68 | * @param size a Integer number for the tree max size 69 | * @return An Integer max tree size 70 | */ 71 | private int setMaxTreeHeight(int size) { 72 | this.maxTreeHeight = size; 73 | return size; 74 | } 75 | 76 | /** 77 | * Searches for an search key number in the tree. If the number is found the tree will 78 | * be repainted to show the path. If the number cannot be found a notification 79 | * message will be displayed. 80 | * 81 | * @param searchKey a Integer number for finding a tree.TreeNode 82 | */ 83 | public void search(Integer searchKey) { 84 | 85 | // Try to search for a number. 86 | try { 87 | tree.retrieveItem(searchKey); // number was found 88 | } catch (NullPointerException e) { // Not found 89 | //JOptionPane.showMessageDialog(null, searchKey + " was not found."); 90 | tree.setResetColor(tree.root); // Reset color 91 | } 92 | 93 | drawTree(); 94 | } 95 | 96 | /** 97 | * Prints the tree traversal order to the upper left-hand 98 | * side of the screen. 99 | * @return outputString 100 | */ 101 | public String printTree() { 102 | 103 | // Traversal text output string 104 | StringBuilder outputString = new StringBuilder(); 105 | 106 | // Add the next tree iterator to the output 107 | while (treeIterator.hasNext()) { 108 | outputString.append(treeIterator.next()).append(" "); 109 | } 110 | 111 | return outputString.toString(); // return the output string 112 | } 113 | 114 | /** 115 | * Retrieves the pre-order traversal option. 116 | */ 117 | public void setPreorder() { 118 | treeIterator = new TreeIterator(tree); 119 | treeIterator.setPreorder(); 120 | } 121 | 122 | /** 123 | * Retrieves the in-order traversal option. 124 | */ 125 | public void setInorder() { 126 | treeIterator = new TreeIterator(tree); 127 | treeIterator.setInorder(); 128 | } 129 | 130 | /** 131 | * Retrieves the post-order traversal option. 132 | */ 133 | public void setPostorder() { 134 | treeIterator = new TreeIterator(tree); 135 | treeIterator.setPostorder(); 136 | } 137 | 138 | /** 139 | * Inserts a circle into the tree. If the tree height reaches the max height 140 | * displays an notification request to change the max height. 141 | * @param searchKey a integer number to insert in the tree 142 | */ 143 | public void insert(Integer searchKey) { 144 | insertCircle = new Circle(searchKey); 145 | tree.insertItem(insertCircle); 146 | int heightOption = 2; 147 | drawTree(); 148 | 149 | 150 | // If the height of the tree equals max height 151 | if (tree.getHeight(tree.getRoot()) == maxTreeHeight) { 152 | // Display option message 153 | 154 | Alert alert = new Alert(Alert.AlertType.WARNING, "Reached max height. Would you like to increase the height?", 155 | ButtonType.YES); 156 | alert.showAndWait() 157 | .filter(response -> response == ButtonType.YES) 158 | .ifPresent(response -> alert.close()); 159 | } 160 | // heightOption = JOptionPane.showConfirmDialog(null, 161 | // "Reached max height. Would you like to increase the height?", " Height Adjust", 162 | // JOptionPane.YES_NO_OPTION); 163 | 164 | // Option 'Yes'selected: Change the height 165 | if (heightOption == 0) { 166 | // String height = JOptionPane.showInputDialog("Enter a new height between 7 and 10."); 167 | heightOption = 7; 168 | try { 169 | int newHeight = heightOption; 170 | // int newHeight = Integer.parseInt(heightOption); 171 | // Confirm height input is within acceptable range 172 | if (newHeight > tree.getHeight(tree.getRoot()) && newHeight <= 10) { 173 | setMaxTreeHeight(newHeight); 174 | } else { 175 | throw new TreeException("tree.TreeException on change height."); 176 | } 177 | 178 | // Error occurred: Reverse changes and exit 179 | } catch (NumberFormatException | TreeException e) { 180 | Alert alert = new Alert(Alert.AlertType.WARNING, "Input error. The height was not changed.", 181 | ButtonType.OK); 182 | alert.showAndWait() 183 | .filter(response -> response == ButtonType.OK) 184 | .ifPresent(response -> alert.close()); 185 | 186 | tree.deleteItem(insertCircle.getSearchKey()); // Remove the inserted circle 187 | tree.setResetColor(tree.root); // Reset highlight flag for all nodes 188 | } 189 | 190 | // Option 'No' selected: Reverse changes and exit 191 | } else if (heightOption == 1) { 192 | Alert alert = new Alert(Alert.AlertType.CONFIRMATION, "The number was not inserted.", 193 | ButtonType.OK); 194 | alert.showAndWait() 195 | .filter(response -> response == ButtonType.OK) 196 | .ifPresent(response -> alert.close()); 197 | 198 | 199 | tree.deleteItem(insertCircle.getSearchKey()); // Remove the inserted circle 200 | tree.setResetColor(tree.root); // Reset highlight flag for all nodes 201 | 202 | 203 | 204 | } else { 205 | 206 | } 207 | } 208 | 209 | /** 210 | * Deletes a number from the tree. If the number is not able to be deleted display 211 | * a notification message. 212 | * @param searchKey integer number to delete from the tree 213 | */ 214 | public void delete(Integer searchKey) { 215 | try { 216 | tree.deleteItem(searchKey); 217 | } catch (TreeException e) { 218 | //JOptionPane.showMessageDialog(null, "Unable to delete " + searchKey); 219 | } 220 | 221 | drawTree(); 222 | } 223 | 224 | /** 225 | * Deletes all the nodes in the tree. 226 | */ 227 | public void makeEmpty() { 228 | tree.makeEmpty(); 229 | maxTreeHeight = 6; 230 | getGraphicsContext2D().clearRect(0, 0, getWidth(), getHeight()); 231 | } 232 | 233 | /** 234 | * Draws the binary tree on the component. 235 | */ 236 | protected void drawTree() { 237 | double width = getWidth(); 238 | double height = getHeight(); 239 | 240 | GraphicsContext gc = getGraphicsContext2D(); 241 | gc.clearRect(0, 0, width, height); 242 | 243 | // If the tree is not empty; draw the lines and circles 244 | if (tree.root != null) { 245 | int treeHeight = tree.getHeight(tree.root); 246 | 247 | // Get the tree height 248 | drawTree(gc, tree.getRoot(), 0, this.getWidth(), 0, this.getHeight() / treeHeight); 249 | drawCircles(gc, tree.getRoot(), 0, this.getWidth(), 0, this.getHeight() / treeHeight); 250 | } 251 | } 252 | 253 | /** 254 | * Draws the lines recursively until there are no more tree nodes. 255 | * @param gc graphics2D class for extending drawing tools 256 | * @param treeNode a tree with integer index numbers 257 | * @param xMin the minimum width to draw on the component 258 | * @param xMax the minimum width to draw on the component 259 | * @param yMin the maximum width to draw on the component 260 | * @param yMax the maximum height to draw on the component 261 | */ 262 | protected void drawTree(GraphicsContext gc, TreeNode treeNode, double xMin, double xMax, double yMin, double yMax) { 263 | 264 | Point2D linePoint1; // Point_1 265 | Point2D linePoint2; // Point_2 266 | Line newLine = new Line(); // Blank line 267 | 268 | // If left node is not null then draw a line to it 269 | if (treeNode.leftCircle != null) { 270 | newLine.setHighlighter(false); 271 | 272 | if (treeNode.leftCircle.highlightFlag) { 273 | newLine.setHighlighter(true); 274 | } 275 | 276 | // Determine the start and end points of the line 277 | linePoint1 = new Point2D(((xMin + xMax) / 2), yMin + yMax / 2); 278 | linePoint2 = new Point2D(((xMin + (xMin + xMax) / 2) / 2), yMin + yMax + yMax / 2); 279 | newLine.setPoint(linePoint1, linePoint2);// Set the points 280 | newLine.draw(gc);// Draw the line 281 | 282 | // Recurse left circle nodes 283 | drawTree(gc, treeNode.leftCircle, xMin, (xMin + xMax) / 2, yMin + yMax, yMax); 284 | } 285 | 286 | // If right node is not null then draw a line to it 287 | if (treeNode.rightCircle != null) { 288 | newLine.setHighlighter(false); 289 | 290 | // Color the line if the tree circle is flagged for color 291 | if (treeNode.rightCircle.highlightFlag) { 292 | newLine.setHighlighter(true); 293 | } 294 | 295 | // Determine the start and end points of the line 296 | linePoint1 = new Point2D((xMin + xMax) / 2, yMin + yMax / 2); 297 | linePoint2 = new Point2D((xMax + (xMin + xMax) / 2) / 2, yMin + yMax + yMax / 2); 298 | newLine.setPoint(linePoint1, linePoint2); 299 | newLine.draw(gc);// Draw the line 300 | 301 | // Recurse right circle nodes 302 | drawTree(gc, treeNode.rightCircle, (xMin + xMax) / 2, xMax, yMin + yMax, yMax); 303 | } 304 | } 305 | 306 | /** 307 | * Draws circles for every root, parent and child tree nodes. 308 | * @param gc graphics2D class for expanding the drawing tools 309 | * @param treeNode a tree with Integer index numbers 310 | * @param xMin the minimum width to draw on the component 311 | * @param xMax the maximum width to draw on the component 312 | * @param yMin the minimum height to draw on the component 313 | * @param yMax the maximum height to draw on the component 314 | */ 315 | public void drawCircles(GraphicsContext gc, TreeNode treeNode, double xMin, double xMax, double yMin, double yMax) { 316 | 317 | // Create a new point 318 | Point2D point = new Point2D((xMin + xMax) / 2, yMin + yMax / 2); 319 | 320 | // treeNodes are flagged for highlight: Search and insertion nodes 321 | if (treeNode.highlightFlag || Objects.equals(treeNode.rootCircle, insertCircle)) { 322 | insertCircle = null; // Reset insert circle 323 | treeNode.highlightFlag = false; // Reset highlight flag 324 | treeNode.rootCircle.setHighlighter(true); // Highlight turned on 325 | treeNode.rootCircle.setPoint(point); 326 | 327 | // default no highlight 328 | } else { 329 | treeNode.rootCircle.setHighlighter(false); // Highlight turned off 330 | treeNode.rootCircle.setPoint(point); 331 | } 332 | 333 | // Draw the circle 334 | treeNode.rootCircle.draw(gc); 335 | 336 | // Recurse left circles 337 | if (treeNode.leftCircle != null) { 338 | drawCircles(gc, treeNode.leftCircle, xMin, (xMin + xMax) / 2, yMin + yMax, yMax); 339 | } 340 | 341 | // Recurse right circles 342 | if (treeNode.rightCircle != null) { 343 | drawCircles(gc, treeNode.rightCircle, (xMin + xMax) / 2, xMax, yMin + yMax, yMax); 344 | } 345 | } 346 | 347 | public void clearCanvas() { 348 | getGraphicsContext2D().clearRect(0, 0, this.getWidth(), this.getHeight()); 349 | } 350 | } 351 | 352 | 353 | -------------------------------------------------------------------------------- /src/main/java/shape/Circle.java: -------------------------------------------------------------------------------- 1 | package shape; 2 | 3 | import com.sun.javafx.tk.FontMetrics; 4 | import com.sun.javafx.tk.Toolkit; 5 | import javafx.geometry.Point2D; 6 | import javafx.scene.canvas.GraphicsContext; 7 | import javafx.scene.paint.Color; 8 | import javafx.scene.text.Font; 9 | import javafx.scene.text.FontWeight; 10 | 11 | 12 | /** 13 | * Creates a circle object with methods for controlling it's point locale, 14 | * background color, border color, font color, and number id. 15 | * @author Eric Canull 16 | * @version 1.0 17 | */ 18 | public final class Circle { 19 | 20 | /** 21 | * The font for the numbers inside the circle. 22 | */ 23 | final Font font = Font.font("Cooper Black", FontWeight.BOLD, 16); 24 | final FontMetrics fm = Toolkit.getToolkit().getFontLoader().getFontMetrics(font); 25 | 26 | /** 27 | * The radius of the circle. 28 | */ 29 | public static final int RADIUS = 26; 30 | 31 | /** 32 | * The search key for searching and deleting circles. 33 | */ 34 | private final Integer searchKey; 35 | 36 | // The circle attributes 37 | private Point2D point; 38 | private Color backgroundColor; 39 | private Color borderColor; 40 | private Color fontColor; 41 | 42 | /** 43 | * Creates a circle object with methods for controlling it's point locale, 44 | * background color, border color, font color, search key. 45 | * @param searchKey a Integer search key for searching and deleting within an index. 46 | */ 47 | public Circle(Integer searchKey) { 48 | this.searchKey = searchKey; 49 | this.backgroundColor = Color.web("#FCFCFC"); 50 | } 51 | 52 | /** 53 | * 54 | * @param searchKey a integer id number for searching and deleting from an index. 55 | * @param point a Cartesian coordinate using x and y float numbers. 56 | */ 57 | public Circle(Integer searchKey, Point2D point) { 58 | this.searchKey = searchKey; 59 | this.point = point; 60 | this.backgroundColor = Color.rgb(49, 116, 222); 61 | this.setBorderColor(Color.rgb(99, 99, 99)); 62 | this.fontColor = Color.web("#FCFCFC"); 63 | 64 | } 65 | 66 | /** 67 | * Draws the circle at a new position 68 | * @param gc The graphics object to use for drawing to a component 69 | */ 70 | public void draw(GraphicsContext gc) { 71 | //(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 72 | gc.setLineWidth(3); // Sets the width of the lines 73 | 74 | // Create a circle 75 | gc.setFill(backgroundColor); 76 | gc.fillOval(point.getX() - RADIUS, point.getY() - RADIUS, 2 * RADIUS, 2 * RADIUS); 77 | 78 | // Outline the circle border 79 | gc.setStroke(borderColor); 80 | gc.strokeOval(point.getX() - RADIUS, point.getY() - RADIUS, 2 * RADIUS, 2 * RADIUS); 81 | 82 | // Draw the id number inside the circle 83 | gc.setFont(font); 84 | gc.setFill(getFontColor()); 85 | gc.fillText(getKey(), 86 | point.getX() - (fm.computeStringWidth(getKey()) / 2), 87 | point.getY() + (fm.getAscent() / 4)); 88 | } 89 | 90 | private String getKey() { 91 | return Integer.toString(getSearchKey()); 92 | } 93 | /** 94 | * Get the search key number. 95 | * @return A integer of the circle index value. 96 | */ 97 | public Integer getSearchKey() { 98 | return this.searchKey; 99 | } 100 | 101 | /** 102 | * Gets the border color. 103 | * @return A color for the circle border 104 | */ 105 | public Color getBorderColor() { 106 | return borderColor; 107 | } 108 | 109 | /** 110 | * Sets the border color. 111 | * @param borderColor 112 | */ 113 | private void setBorderColor(Color borderColor) { 114 | this.borderColor = borderColor; 115 | } 116 | 117 | /** 118 | * Gets the point coordinates. 119 | * @return 120 | */ 121 | public Point2D getPoint() { 122 | return point; 123 | } 124 | 125 | /** 126 | * Sets the point coordinates. 127 | * @param point 128 | */ 129 | public void setPoint(Point2D point) { 130 | this.point = point; 131 | } 132 | 133 | /** 134 | * Gets the background color. 135 | * @return 136 | */ 137 | public Color getBackgroundColor() { 138 | return backgroundColor; 139 | } 140 | 141 | /** 142 | * Sets the background color. 143 | * @param color 144 | */ 145 | private void setBackgroundColor(Color color) { 146 | this.backgroundColor = color; 147 | } 148 | 149 | /** 150 | * Gets the circle radius. 151 | * @return 152 | */ 153 | public int getRadius() { 154 | return RADIUS; 155 | } 156 | 157 | /** 158 | * Gets the font color. 159 | * @return 160 | */ 161 | public Color getFontColor() { 162 | return this.fontColor; 163 | } 164 | 165 | /** 166 | * Sets the font color. 167 | * @param fontColor 168 | */ 169 | private void setFontColor(Color fontColor) { 170 | this.fontColor = fontColor; 171 | } 172 | 173 | /** 174 | * Sets the circle to use highlighted colors if the parameter 175 | * is true. 176 | * @param highlight a boolean value for switching on/off highlighted colors 177 | */ 178 | public void setHighlighter(boolean highlight) { 179 | if (highlight) { 180 | setFontColor(Color.rgb(49, 116, 222)); 181 | setBackgroundColor(Color.rgb(155, 244, 167)); 182 | setBorderColor(Color.rgb(49, 116, 222)); 183 | 184 | } else { 185 | setFontColor(Color.web("#FCFCFC")); 186 | setBackgroundColor(Color.rgb(49, 116, 222)); 187 | setBorderColor(Color.rgb(99, 99, 99)); 188 | } 189 | } 190 | 191 | /** 192 | * Overrides the default toString method and gets the String representation 193 | * of a circle. 194 | * @return A String representation of the circle object. 195 | */ 196 | @Override 197 | public String toString() { 198 | 199 | return "Search Key# " + searchKey + 200 | " (x,y) = (" + point.getX() + ", " + point.getY() + ")"; 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /src/main/java/shape/Line.java: -------------------------------------------------------------------------------- 1 | package shape; 2 | 3 | import javafx.geometry.Point2D; 4 | import javafx.scene.canvas.GraphicsContext; 5 | import javafx.scene.paint.Color; 6 | 7 | /** 8 | * Creates a line object with methods for controlling it's point locale, 9 | * color, and size. 10 | * @author Eric Canull 11 | * @version 1.0 12 | */ 13 | public final class Line { 14 | 15 | /** 16 | * Default color is the panel foreground. 17 | */ 18 | private static final Color UI_DEFAULT_COLOR = Color.rgb(99, 99, 99); 19 | 20 | /** 21 | * Highlight color for searching and inserting. 22 | */ 23 | private static final Color HIGHLIGHT_COLOR = Color.rgb(49, 116, 222); 24 | 25 | // The circle attributes 26 | private Point2D point, point2; 27 | private Color color; 28 | 29 | /** 30 | * Creates a line object with methods for controlling it's point locale, 31 | * background color, border color, font color, and number id. 32 | */ 33 | public Line() { 34 | this.color = UI_DEFAULT_COLOR; 35 | } 36 | 37 | /** 38 | * 39 | * @param point a Cartesian coordinate using x and y float numbers. 40 | */ 41 | public Line(Point2D point, Point2D point2) { 42 | this.point = point; 43 | this.point2 = point; 44 | this.color = UI_DEFAULT_COLOR; 45 | } 46 | 47 | /** 48 | * Draws the line at a specified position 49 | * @param gc The graphics object to use for drawing to a component 50 | */ 51 | public void draw(GraphicsContext gc) { 52 | // g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 53 | gc.setLineWidth(4); // Sets the width of the lines 54 | 55 | // Fill the line 56 | gc.setStroke(color); 57 | gc.strokeLine(point.getX(), point.getY(), point2.getX(), point2.getY()); 58 | } 59 | 60 | /** 61 | * Gets the point coordinates. 62 | * @return A point 63 | */ 64 | public Point2D getPoint() { 65 | return point; 66 | } 67 | 68 | /** 69 | * Sets the point coordinates. 70 | * @param point A Cartesian coordinate 71 | */ 72 | public void setPoint(Point2D point, Point2D point2) { 73 | this.point = point; 74 | this.point2 = point2; 75 | } 76 | 77 | /** 78 | * Gets the point coordinates. 79 | * @return A Cartesian coordinate 80 | */ 81 | public Point2D getPoint2() { 82 | return point2; 83 | } 84 | 85 | /** 86 | * Sets the line to use highlighted colors if the parameter 87 | * is true. 88 | * @param highlight a boolean value for switching on/off highlighted colors 89 | */ 90 | public void setHighlighter(boolean highlight) { 91 | if (highlight) { 92 | this.color = HIGHLIGHT_COLOR; 93 | } else { 94 | this.color = UI_DEFAULT_COLOR; 95 | } 96 | } 97 | 98 | /** 99 | * Overrides the default toString method and gets the String representation 100 | * of a line. 101 | * @return A String representation of the line 102 | */ 103 | @Override 104 | public String toString() { 105 | 106 | return " (x,y) = (" + point.getX() + ", " + point.getY() + ")" 107 | + " (x,y) = (" + point2.getX() + ", " + point2.getY()+ ")"; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/tree/BinarySearchTree.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | import java.util.Objects; 4 | import shape.Circle; 5 | 6 | /** 7 | * Binary search tree. 8 | * Inherits isEmpty(), makeEmpty(), getRootItem(), and the 9 | * use of the constructors from tree.BinaryTreeBasis Assumption: A tree contains at 10 | * most one item with a given search key at any time. 11 | * 12 | * @author Eric Canull 13 | * @version 1.0 14 | */ 15 | public final class BinarySearchTree extends BinaryTreeBasis { 16 | 17 | /** 18 | * Binary search tree. 19 | */ 20 | public BinarySearchTree() { 21 | this.root = null; 22 | } 23 | 24 | /** 25 | * Binary search tree. 26 | * @param rootCircle 27 | * @Overload Default constructor 28 | */ 29 | public BinarySearchTree(Circle rootCircle) { 30 | super(rootCircle); 31 | } 32 | 33 | /** 34 | * Inserts a new circle into the tree. 35 | * @param newCircle 36 | */ 37 | public void insertItem(Circle newCircle) { 38 | root = insertItem(root, newCircle); 39 | } 40 | 41 | /** 42 | * Inserts a new circle into the tree. 43 | * @param tNode a tree node 44 | * @param newCircle a new circle 45 | * @return 46 | * @Overload insertItem() 47 | */ 48 | protected TreeNode insertItem(TreeNode tNode, Circle newCircle) { 49 | TreeNode newSubtree; 50 | 51 | if (tNode == null) { 52 | tNode = new TreeNode(newCircle, null, null); 53 | return tNode; 54 | } 55 | 56 | Circle nodeItem = tNode.rootCircle; 57 | 58 | if(Objects.equals(newCircle.getSearchKey(), nodeItem.getSearchKey())) { 59 | return tNode; 60 | } 61 | 62 | if (newCircle.getSearchKey() < nodeItem.getSearchKey()) { 63 | newSubtree = insertItem(tNode.leftCircle, newCircle); 64 | tNode.leftCircle = newSubtree; 65 | return tNode; 66 | } 67 | 68 | newSubtree = insertItem(tNode.rightCircle, newCircle); 69 | tNode.rightCircle = newSubtree; 70 | return tNode; 71 | } 72 | 73 | /** 74 | * Retrieves a circle from the tree. 75 | * @param searchKey a unique identifying value 76 | * @return An integer search key number 77 | */ 78 | public Integer retrieveItem(Integer searchKey) { 79 | return retrieveItem(root, searchKey); 80 | } 81 | 82 | 83 | /** 84 | * Searches for a circle from the tree. 85 | * @param tNode a tree node 86 | * @param searchKey a unique identifying value 87 | * @return An integer search key number 88 | * @Overload retrieveItem() 89 | */ 90 | protected Integer retrieveItem(TreeNode tNode, Integer searchKey) { 91 | Integer treeItem; 92 | if (tNode == null) { 93 | treeItem = null; 94 | 95 | } else { 96 | tNode.highlightFlag = true; 97 | Circle nodeItem = tNode.rootCircle; 98 | if (Objects.equals(searchKey, nodeItem.getSearchKey())) { 99 | tNode.highlightFlag = true; 100 | treeItem = tNode.rootCircle.getSearchKey(); 101 | } else if (searchKey < nodeItem.getSearchKey()) { 102 | tNode.leftCircle.highlightFlag = true; 103 | treeItem = retrieveItem(tNode.leftCircle, searchKey); 104 | } else { 105 | tNode.rightCircle.highlightFlag = true; 106 | treeItem = retrieveItem(tNode.rightCircle, searchKey); 107 | } 108 | } 109 | 110 | return treeItem; 111 | } 112 | 113 | /** 114 | * Deletes a circle from the tree. 115 | * @param searchKey a unique identifying value 116 | * @throws TreeException if search key cannot be located. 117 | */ 118 | public void deleteItem(Integer searchKey) throws TreeException { 119 | root = deleteItem(root, searchKey); 120 | } 121 | 122 | /** 123 | * Deletes a circle from the tree. 124 | * @param tNode a tree node 125 | * @param searchKey a unique identifying value 126 | * @return A tree.TreeNode from within the tree 127 | * @Overload deleteItem() 128 | */ 129 | protected TreeNode deleteItem(TreeNode tNode, Integer searchKey) { 130 | TreeNode newSubtree; 131 | 132 | if (tNode == null) { 133 | throw new TreeException("tree.TreeException: Item not found"); 134 | } 135 | 136 | Circle nodeItem = tNode.rootCircle; 137 | if (Objects.equals(searchKey, nodeItem.getSearchKey())) { 138 | tNode = deleteNode(tNode); 139 | 140 | } else if (searchKey < nodeItem.getSearchKey()) { 141 | newSubtree = deleteItem(tNode.leftCircle, searchKey); 142 | tNode.leftCircle = newSubtree; 143 | } 144 | 145 | else { 146 | newSubtree = deleteItem(tNode.rightCircle, searchKey); 147 | tNode.rightCircle = newSubtree; 148 | } 149 | 150 | return tNode; 151 | } 152 | 153 | /** 154 | * Helper method finds and replaces a deleted node. 155 | * @param tNode A tree.TreeNode from within the tree 156 | * @return A tree.TreeNode from within the tree 157 | */ 158 | protected TreeNode deleteNode(TreeNode tNode) { 159 | 160 | Circle replacementItem; 161 | 162 | if ((tNode.leftCircle == null) && (tNode.rightCircle == null)) { 163 | return null; 164 | } 165 | 166 | else if (tNode.leftCircle == null) { 167 | return tNode.rightCircle; 168 | } 169 | 170 | else if (tNode.rightCircle == null) { 171 | return tNode.leftCircle; 172 | } else { 173 | 174 | replacementItem = findLeftmost(tNode.rightCircle); 175 | tNode.rootCircle = replacementItem; 176 | tNode.rightCircle = deleteLeftmost(tNode.rightCircle); 177 | return tNode; 178 | } 179 | } 180 | 181 | /** 182 | * Helper method for searching and deleting left-side nodes. 183 | * @param tNode 184 | * @return 185 | */ 186 | protected Circle findLeftmost(TreeNode tNode) { 187 | if (tNode.leftCircle == null) { 188 | return tNode.rootCircle; 189 | } 190 | return findLeftmost(tNode.leftCircle); 191 | } 192 | 193 | /** 194 | * Helper method for searching and deleting right-side nodes. 195 | * @param tNode 196 | * @return 197 | */ 198 | protected TreeNode deleteLeftmost(TreeNode tNode) { 199 | if (tNode.leftCircle == null) { 200 | return tNode.rightCircle; 201 | } 202 | tNode.leftCircle = deleteLeftmost(tNode.leftCircle); 203 | return tNode; 204 | } 205 | 206 | /** 207 | * Resets the color to the default. 208 | * @param tNode 209 | */ 210 | public void setResetColor(TreeNode tNode) { 211 | resetColor(tNode); 212 | } 213 | 214 | 215 | /** 216 | * Resets the color to the default. 217 | * @param tNode A node in the tree 218 | * @Overload 219 | */ 220 | protected void resetColor(TreeNode tNode) { 221 | if (tNode != null) { 222 | tNode.highlightFlag = false; 223 | 224 | if (tNode.leftCircle != null) { 225 | tNode.leftCircle.highlightFlag = false; 226 | } 227 | 228 | if (tNode.rightCircle != null) { 229 | tNode.rightCircle.highlightFlag = false; 230 | } 231 | resetColor(tNode.leftCircle); 232 | resetColor(tNode.rightCircle); 233 | } 234 | } 235 | 236 | /** 237 | * Gets the height of the tree 238 | * @param root 239 | * @return 240 | */ 241 | public int getHeight(TreeNode root) { 242 | if (root == null) 243 | return 0; 244 | return Math.max(getHeight(root.leftCircle), getHeight(root.rightCircle)) + 1; 245 | } 246 | 247 | /** 248 | * Gets the size of the tree 249 | * @param root 250 | * @return 251 | */ 252 | public int getSize(TreeNode root) { 253 | if (root == null) 254 | return 0; 255 | return (getSize(root.leftCircle) + getSize(root.rightCircle)) + 1; 256 | } 257 | 258 | @Override 259 | public void setRootItem(Circle newItem) { 260 | root = new TreeNode(newItem, null, null); 261 | } 262 | } 263 | -------------------------------------------------------------------------------- /src/main/java/tree/BinaryTreeBasis.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | import shape.Circle; 4 | 5 | /** 6 | * An abstract base class for a binary tree. 7 | * @author Eric Canull 8 | */ 9 | public abstract class BinaryTreeBasis { 10 | 11 | /** 12 | * Inherited by the concrete BST class. 13 | */ 14 | public TreeNode root; 15 | 16 | /** 17 | * An abstract base class for the BST. 18 | */ 19 | public BinaryTreeBasis() { 20 | root = null; 21 | } 22 | 23 | /** 24 | * An abstract base class for the BST. 25 | * @param rootCircle 26 | * @Overload Default constructor 27 | */ 28 | public BinaryTreeBasis(Circle rootCircle) { 29 | root = new TreeNode(rootCircle, null, null); 30 | } 31 | 32 | /** 33 | * Checks if the tree is empty. 34 | * @return true if the tree has items 35 | */ 36 | public boolean isEmpty() { 37 | return root == null; 38 | } 39 | 40 | /** 41 | * Makes the tree empty. 42 | */ 43 | public void makeEmpty() { 44 | root = null; 45 | } 46 | 47 | /** 48 | * Gets the root item. 49 | * @return A shape.Circle object representing the tree root 50 | * @throws TreeException 51 | */ 52 | public TreeNode getRoot() throws TreeException { 53 | if (root == null) { 54 | throw new TreeException("tree.TreeException: Empty Tree"); 55 | } 56 | 57 | return root; 58 | } 59 | 60 | /** 61 | * Sets the root item. 62 | * @param newCircle a shape.Circle object with a tree search key 63 | */ 64 | public abstract void setRootItem(Circle newCircle); 65 | 66 | } -------------------------------------------------------------------------------- /src/main/java/tree/QueueException.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | /** 4 | * Defines an exception that is thrown when a queue exception occurs. 5 | */ 6 | @SuppressWarnings("serial") 7 | public final class QueueException extends RuntimeException { 8 | 9 | /** 10 | * Constructs an object with specific message 11 | * @param message A string literal specifying the details of this exception 12 | */ 13 | public QueueException(String message) { 14 | super(message); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/tree/TreeException.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | /** 4 | * Defines an exception that is thrown when tree exception occurs. 5 | */ 6 | @SuppressWarnings("serial") 7 | public final class TreeException extends RuntimeException { 8 | 9 | /** 10 | * Constructs an object with specific message 11 | * @param message A string literal specifying the details of this exception 12 | */ 13 | public TreeException(String message) { 14 | super(message); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/tree/TreeIterator.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | import java.util.Iterator; 4 | import java.util.LinkedList; 5 | import java.util.NoSuchElementException; 6 | 7 | /** 8 | * Iterates through the tree using the java.util.Iterator interface. 9 | * @author Eric Canull 10 | * @version 1.0 11 | */ 12 | public final class TreeIterator implements Iterator { 13 | 14 | private BinaryTreeBasis binaryTree; 15 | private TreeNode currentNode; 16 | private LinkedList queue; 17 | 18 | /** 19 | * Iterates through the tree using the java.util.Iterator interface. 20 | * @param binaryTree the abstract binary tree class 21 | */ 22 | public TreeIterator(BinaryTreeBasis binaryTree) { 23 | this.binaryTree = binaryTree; 24 | currentNode = null; 25 | queue = new LinkedList<>(); 26 | } 27 | 28 | /** 29 | * Determines if there are elements in the queue. 30 | * @Return true if the iteration has more elements 31 | */ 32 | public boolean hasNext() { 33 | return !queue.isEmpty(); 34 | } 35 | 36 | /** 37 | * Gets the next element in the queue. 38 | * @return An Integer numbered search key. 39 | */ 40 | public Integer next() throws NoSuchElementException { 41 | try { 42 | currentNode = queue.remove(); 43 | return currentNode.rootCircle.getSearchKey(); 44 | } catch (QueueException e) { 45 | throw new NoSuchElementException(); 46 | } 47 | } 48 | 49 | /** 50 | * Unsupported remove operation. Throws an exception when invoked. 51 | */ 52 | public void remove() throws UnsupportedOperationException { 53 | throw new UnsupportedOperationException(); 54 | } 55 | 56 | /** 57 | * Sets the tree traversal to in-order 58 | */ 59 | public void setPreorder() { 60 | queue.clear(); 61 | preorder(binaryTree.root); 62 | } 63 | 64 | /** 65 | * Recursively traverses the tree in-order 66 | * @param treeNode A tree with nodes 67 | */ 68 | private void preorder(TreeNode treeNode) { 69 | if (treeNode != null) { 70 | queue.add(treeNode); 71 | preorder(treeNode.leftCircle); 72 | preorder(treeNode.rightCircle); 73 | } 74 | } 75 | 76 | /** 77 | * Sets the tree traversal to in-order 78 | */ 79 | public void setInorder() { 80 | queue.clear(); 81 | inorder(binaryTree.root); 82 | } 83 | 84 | /** 85 | * Recursively traverses the tree in-order 86 | * @param treeNode A tree with nodes 87 | */ 88 | private void inorder(TreeNode treeNode) { 89 | if (treeNode != null) { 90 | inorder(treeNode.leftCircle); 91 | queue.add(treeNode); 92 | inorder(treeNode.rightCircle); 93 | } 94 | } 95 | 96 | /** 97 | * Sets the tree to traverse in post-order 98 | */ 99 | public void setPostorder() { 100 | queue.clear(); 101 | postorder(binaryTree.root); 102 | } 103 | 104 | /** 105 | * Recursively traverses the tree post-order 106 | * @param treeNode A tree with nodes 107 | */ 108 | private void postorder(TreeNode treeNode) { 109 | if (treeNode != null) { 110 | postorder(treeNode.leftCircle); 111 | postorder(treeNode.rightCircle); 112 | queue.add(treeNode); 113 | } 114 | } 115 | } -------------------------------------------------------------------------------- /src/main/java/tree/TreeNode.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | import shape.Circle; 4 | 5 | /** 6 | * A binary tree using circle objects. 7 | * @author Eric Canull 8 | * @version 1.0 9 | */ 10 | public class TreeNode { 11 | 12 | public Circle rootCircle; 13 | public TreeNode leftCircle; 14 | public TreeNode rightCircle; 15 | public boolean highlightFlag; 16 | 17 | /** 18 | * A binary tree using circle objects. 19 | * @param rootCircle a root tree circle 20 | * @param leftCircle a left tree circle 21 | * @param rightCircle a right tree circle 22 | */ 23 | public TreeNode(Circle rootCircle, TreeNode leftCircle, TreeNode rightCircle) { 24 | this.rootCircle = rootCircle; 25 | this.leftCircle = null; 26 | this.rightCircle = null; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/resources/fxml/FXMLGraphicsPanel.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |