├── .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 |
20 |
21 |
22 |
23 |
24 |
25 |
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 |
131 |
132 |
133 |
136 |
137 |
138 |
159 |
160 |
161 |
162 |
163 | true
164 | DEFINITION_ORDER
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
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 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 |
631 |
632 |
633 |
634 |
635 |
636 |
637 |
638 |
639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 |
647 |
648 |
649 |
650 |
651 |
652 |
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 |
665 |
666 |
667 |
668 |
669 |
670 |
671 |
672 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 |
699 |
700 |
701 |
702 |
703 |
704 |
705 |
706 |
707 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
718 |
719 |
720 |
721 |
722 |
723 |
724 |
725 |
726 |
727 |
728 |
729 |
730 |
731 |
732 |
733 |
734 |
735 |
736 |
737 |
738 |
739 |
740 |
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 |
774 |
775 |
776 |
777 |
778 | 1499366758985
779 |
780 |
781 | 1499366758985
782 |
783 |
784 |
785 |
786 |
787 |
788 |
789 |
790 |
791 |
792 |
793 |
794 |
795 |
796 |
797 |
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 |
836 |
837 |
838 |
839 |
840 |
841 |
842 |
843 |
844 | file://$PROJECT_DIR$/src/main/java/tree/BinaryTreeBasis.java
845 | 19
846 |
847 |
848 |
849 |
850 |
851 |
852 |
853 |
854 |
855 |
856 |
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 |
1374 |
1375 |
1376 |
1377 |
1378 |
1379 |
1380 |
1381 |
1382 |
1383 | No facets are configured
1384 |
1385 |
1386 |
1387 |
1388 |
1389 |
1390 |
1391 |
1392 |
1393 |
1394 |
1395 |
1396 |
1397 |
1398 |
1399 |
1400 |
1401 |
1402 |
1403 |
1404 |
1405 |
1406 | 1.8
1407 |
1408 |
1409 |
1410 |
1411 |
1412 |
1413 |
1414 |
1415 |
1416 |
1417 |
1418 | fxbinarytree
1419 |
1420 |
1421 |
1422 |
1423 |
1424 |
1425 |
1426 |
1427 |
1428 |
1429 |
1430 |
1431 | 1.8
1432 |
1433 |
1434 |
1435 |
1436 |
1437 |
1438 |
1439 |
1440 |
1441 |
1442 |
1443 |
1444 |
1445 |
1446 |
1447 |
1448 |
1449 |
1450 |
1451 |
1452 |
1453 |
1454 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FXBinaryTree
2 |
3 | Elegant javafx binary tree demo.
4 |
5 | ### Screenshot
6 | 
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 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/src/main/resources/image/binarytree_screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricCanull/fxbinarytree/c03934e133848499173527f26e8677ddb693a493/src/main/resources/image/binarytree_screenshot.png
--------------------------------------------------------------------------------
/src/main/resources/style/graphics_controller.css:
--------------------------------------------------------------------------------
1 | .root {
2 | -fx-font-family: "System";
3 | -fx-font-size: 1em;
4 | -fx-base: #131313;
5 | -fx-background: #2D2D2D;
6 | -fx-focus-color: #7C7C7C;
7 | -fx-control-inner-background: #1C1C1C;
8 | -fx-text-base-color: #CBCCCB;
9 | -fx-text-background-color: #F9F9F9;
10 | -fx-text-inner-color: #C9C9C9;
11 | -fx-inner-border: linear-gradient(to bottom, derive(-fx-color,50%) 0%, derive(-fx-color,-5%) 100%);
12 | -fx-body-color: linear-gradient( to bottom, derive(-fx-color, -2%) 0%, derive(-fx-color, 9%) 50%, derive(-fx-color, -9%) 50.5%, derive(-fx-color, -69%) 100%);
13 | }
14 | .button, .toggle-button, .choice-box {
15 | -fx-background-radius: 5, 5, 4, 3;
16 | -fx-padding: 3px 10px 3px 10px;
17 | }
18 | .menu-button {
19 | -fx-background-radius: 5, 5, 4, 3;
20 | }
21 | .menu-button .label {
22 | -fx-padding: 3px 18px 3px 10px;
23 | }
24 | .menu-button .arrow-button {
25 | -fx-padding: 3px 6px 3px 0px;
26 | }
27 | .choice-box {
28 | -fx-padding: 0 6px 0 0;
29 | }
30 | .choice-box .label {
31 | -fx-padding: 3px 4px 3px 6px;
32 | }
33 | .choice-box .open-button {
34 | -fx-padding: 1 0 0 8px;
35 | }
36 | .combo-box-base:editable .text-field, .combo-box-base .arrow-button, .combo-box .list-cell {
37 | -fx-padding: 3px 6px 3px 6px;
38 | }
39 | .check-box .box {
40 | -fx-padding: 0.25em;
41 | }
42 | .radio-button .radio {
43 | -fx-padding: 0.333333em;
44 | }
45 | .label, .check-box, Text, .radio-button {
46 | -fx-font-family: -fx-font-type; -fx-fill: -fx-text-background-color; -fx-fx-text-fill: -fx-text-background-color;
47 | }
48 | .text {
49 | -fx-font-family: "System";
50 | }
51 | .text-field {
52 | -fx-text-fill: -fx-text-base-color;
53 | -fx-prompt-text-fill: derive(-fx-text-base-color, -20%);
54 | }
55 | .button, .toggle-button, .check-box .box, .radio-button .radio, .choice-box, .menu-button, .tab, .combo-box-base {
56 | -fx-background-insets: 0 0 -1 0, 0, 1, 2;
57 | }
58 | .button:focused, .toggle-button:focused, .check-box:focused .box, .radio-button:focused .radio, .choice-box:focused, .menu-button:focused, .combo-box-base:focused {
59 | -fx-background-insets: -1.4, 0, 1, 2;
60 | }
61 | .combo-box-base .arrow-button {
62 | -fx-background-insets: 0, 1, 2;
63 | }
64 | .choice-box .label { /* Workaround for RT-20015 */
65 | -fx-text-fill: -fx-text-base-color;
66 | }
67 | .menu-button .label { /* Workaround for RT-20015 */
68 | -fx-text-fill: -fx-text-base-color;
69 | }
--------------------------------------------------------------------------------
/target/classes/app/Main.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricCanull/fxbinarytree/c03934e133848499173527f26e8677ddb693a493/target/classes/app/Main.class
--------------------------------------------------------------------------------
/target/classes/controller/GraphicsController.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricCanull/fxbinarytree/c03934e133848499173527f26e8677ddb693a493/target/classes/controller/GraphicsController.class
--------------------------------------------------------------------------------
/target/classes/controller/GraphicsTree.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricCanull/fxbinarytree/c03934e133848499173527f26e8677ddb693a493/target/classes/controller/GraphicsTree.class
--------------------------------------------------------------------------------
/target/classes/fxml/FXMLGraphicsPanel.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/target/classes/shape/Circle.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricCanull/fxbinarytree/c03934e133848499173527f26e8677ddb693a493/target/classes/shape/Circle.class
--------------------------------------------------------------------------------
/target/classes/shape/Line.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricCanull/fxbinarytree/c03934e133848499173527f26e8677ddb693a493/target/classes/shape/Line.class
--------------------------------------------------------------------------------
/target/classes/style/graphics_controller.css:
--------------------------------------------------------------------------------
1 | .root {
2 | -fx-font-family: "System";
3 | -fx-font-size: 1em;
4 | -fx-base: #131313;
5 | -fx-background: #2D2D2D;
6 | -fx-focus-color: #7C7C7C;
7 | -fx-control-inner-background: #1C1C1C;
8 | -fx-text-base-color: #CBCCCB;
9 | -fx-text-background-color: #F9F9F9;
10 | -fx-text-inner-color: #C9C9C9;
11 | -fx-inner-border: linear-gradient(to bottom, derive(-fx-color,50%) 0%, derive(-fx-color,-5%) 100%);
12 | -fx-body-color: linear-gradient( to bottom, derive(-fx-color, -2%) 0%, derive(-fx-color, 9%) 50%, derive(-fx-color, -9%) 50.5%, derive(-fx-color, -69%) 100%);
13 | }
14 | .button, .toggle-button, .choice-box {
15 | -fx-background-radius: 5, 5, 4, 3;
16 | -fx-padding: 3px 10px 3px 10px;
17 | }
18 | .menu-button {
19 | -fx-background-radius: 5, 5, 4, 3;
20 | }
21 | .menu-button .label {
22 | -fx-padding: 3px 18px 3px 10px;
23 | }
24 | .menu-button .arrow-button {
25 | -fx-padding: 3px 6px 3px 0px;
26 | }
27 | .choice-box {
28 | -fx-padding: 0 6px 0 0;
29 | }
30 | .choice-box .label {
31 | -fx-padding: 3px 4px 3px 6px;
32 | }
33 | .choice-box .open-button {
34 | -fx-padding: 1 0 0 8px;
35 | }
36 | .combo-box-base:editable .text-field, .combo-box-base .arrow-button, .combo-box .list-cell {
37 | -fx-padding: 3px 6px 3px 6px;
38 | }
39 | .check-box .box {
40 | -fx-padding: 0.25em;
41 | }
42 | .radio-button .radio {
43 | -fx-padding: 0.333333em;
44 | }
45 | .label, .check-box, Text, .radio-button {
46 | -fx-font-family: -fx-font-type; -fx-fill: -fx-text-background-color; -fx-fx-text-fill: -fx-text-background-color;
47 | }
48 | .text {
49 | -fx-font-family: "System";
50 | }
51 | .text-field {
52 | -fx-text-fill: -fx-text-base-color;
53 | -fx-prompt-text-fill: derive(-fx-text-base-color, -20%);
54 | }
55 | .button, .toggle-button, .check-box .box, .radio-button .radio, .choice-box, .menu-button, .tab, .combo-box-base {
56 | -fx-background-insets: 0 0 -1 0, 0, 1, 2;
57 | }
58 | .button:focused, .toggle-button:focused, .check-box:focused .box, .radio-button:focused .radio, .choice-box:focused, .menu-button:focused, .combo-box-base:focused {
59 | -fx-background-insets: -1.4, 0, 1, 2;
60 | }
61 | .combo-box-base .arrow-button {
62 | -fx-background-insets: 0, 1, 2;
63 | }
64 | .choice-box .label { /* Workaround for RT-20015 */
65 | -fx-text-fill: -fx-text-base-color;
66 | }
67 | .menu-button .label { /* Workaround for RT-20015 */
68 | -fx-text-fill: -fx-text-base-color;
69 | }
--------------------------------------------------------------------------------
/target/classes/tree/BinarySearchTree.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricCanull/fxbinarytree/c03934e133848499173527f26e8677ddb693a493/target/classes/tree/BinarySearchTree.class
--------------------------------------------------------------------------------
/target/classes/tree/BinaryTreeBasis.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricCanull/fxbinarytree/c03934e133848499173527f26e8677ddb693a493/target/classes/tree/BinaryTreeBasis.class
--------------------------------------------------------------------------------
/target/classes/tree/QueueException.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricCanull/fxbinarytree/c03934e133848499173527f26e8677ddb693a493/target/classes/tree/QueueException.class
--------------------------------------------------------------------------------
/target/classes/tree/TreeException.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricCanull/fxbinarytree/c03934e133848499173527f26e8677ddb693a493/target/classes/tree/TreeException.class
--------------------------------------------------------------------------------
/target/classes/tree/TreeIterator.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricCanull/fxbinarytree/c03934e133848499173527f26e8677ddb693a493/target/classes/tree/TreeIterator.class
--------------------------------------------------------------------------------
/target/classes/tree/TreeNode.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricCanull/fxbinarytree/c03934e133848499173527f26e8677ddb693a493/target/classes/tree/TreeNode.class
--------------------------------------------------------------------------------