1
+ import java .util .LinkedList ;
2
+
3
+ public class AVLTree {
4
+
5
+ private class AVLNode {
6
+ private int height ;
7
+ private int value ;
8
+ private AVLNode right ;
9
+ private AVLNode left ;
10
+
11
+ private AVLNode (int value ) {
12
+ this .value = value ;
13
+ }
14
+
15
+ @ Override
16
+ public String toString () {
17
+ return "Node value: " + value + " and its height is: " + height ;
18
+ }
19
+ }
20
+
21
+ AVLNode root ;
22
+
23
+ public void remove (int value ) {
24
+ root = remove (root , value );
25
+ }
26
+
27
+ private AVLNode remove (AVLNode root , int value ) {
28
+ if (root == null )
29
+ return null ;
30
+
31
+
32
+ if (value == root .value ) {
33
+ if (root .right == null && root .left == null )
34
+ return null ;
35
+
36
+ else if (root .right == null ) {
37
+ return root .left ;
38
+ }
39
+
40
+ else {
41
+ AVLNode tempNode = root .right ;
42
+ while (tempNode .left != null )
43
+ tempNode = tempNode .left ;
44
+
45
+ root .value = tempNode .value ;
46
+ root .right = remove (root .right , tempNode .value );
47
+ }
48
+
49
+ }
50
+ else if (value > root .value ) {
51
+ root .right = remove (root .right , value );
52
+ }
53
+ else {
54
+ root .left = remove (root .left , value );
55
+ }
56
+
57
+ root .height = 1 + Math .max (checkIfNodeEmpty (root .left ), checkIfNodeEmpty (root .right ));
58
+
59
+ if (isUnbalanced (root ))
60
+ return rightOrLeftHeavy (root );
61
+
62
+ return root ;
63
+ }
64
+
65
+ public void insert (int value ) {
66
+ root = insert (this .root , value );
67
+ }
68
+
69
+ private AVLNode insert (AVLNode root , int value ) {
70
+ if (root == null )
71
+ return new AVLNode (value );
72
+
73
+ else if (root .value < value )
74
+ root .right = insert (root .right , value );
75
+
76
+ else if (root .value > value )
77
+ root .left = insert (root .left , value );
78
+
79
+ root .height = 1 + Math .max (checkIfNodeEmpty (root .left ), checkIfNodeEmpty (root .right ));
80
+
81
+ if (isUnbalanced (root ))
82
+ return rightOrLeftHeavy (root );
83
+
84
+ return root ;
85
+ }
86
+
87
+ private boolean isUnbalanced (AVLNode node ){
88
+ return (1 + checkIfNodeEmpty (node .left )) - (1 + checkIfNodeEmpty (node .right )) > 1 ||
89
+ (1 + checkIfNodeEmpty (node .left )) - (1 + checkIfNodeEmpty (node .right )) < -1 ;
90
+ }
91
+
92
+ private AVLNode rightOrLeftHeavy (AVLNode node ){
93
+ AVLNode root ;
94
+ if ((1 + checkIfNodeEmpty (node .left )) - (1 + checkIfNodeEmpty (node .right )) > 1 ){
95
+ if (checkForLLOrLR (node )) return leftRotation (node );
96
+ else {
97
+ root = leftRotation (node );
98
+ return rightRotation (root );
99
+ }
100
+ }
101
+
102
+ else if ((1 + checkIfNodeEmpty (node .left )) - (1 + checkIfNodeEmpty (node .right )) < -1 ) {
103
+ if (checkForRROrRL (node )) return rightRotation (node );
104
+ else {
105
+ root = rightRotation (node );
106
+ return leftRotation (root );
107
+ }
108
+ }
109
+ return null ;
110
+ }
111
+
112
+ private boolean checkForLLOrLR (AVLNode node ){
113
+ return (1 + checkIfNodeEmpty (node .left .left )) > (1 + checkIfNodeEmpty (node .left .right ));
114
+ }
115
+
116
+ private boolean checkForRROrRL (AVLNode node ){
117
+ return (1 + checkIfNodeEmpty (node .right .right )) > (1 + checkIfNodeEmpty (node .right .left ));
118
+ }
119
+
120
+ private AVLNode leftRotation (AVLNode node ){
121
+ AVLNode temp = node .left ;
122
+ while (temp .right != null ) temp = temp .right ;
123
+ temp .right = node ;
124
+ AVLNode root = node .left ;
125
+ node .left = null ;
126
+ root = getHeight (root );
127
+ return root ;
128
+ }
129
+
130
+ private AVLNode rightRotation (AVLNode node ){
131
+ AVLNode temp = node .right ;
132
+ while (temp .left != null ) temp = temp .left ;
133
+ temp .left = node ;
134
+ AVLNode root = node .right ;
135
+ node .right = null ;
136
+ root = getHeight (root );
137
+ return root ;
138
+ }
139
+
140
+ private AVLNode getHeight (AVLNode node ){
141
+ if (node == null )
142
+ return node ;
143
+
144
+ node .left = getHeight (node .left );
145
+ node .right = getHeight (node .right );
146
+ node .height = 1 + Math .max (checkIfNodeEmpty (node .left ), checkIfNodeEmpty (node .right ));
147
+
148
+ if (isUnbalanced (node ))
149
+ return rightOrLeftHeavy (node );
150
+
151
+ return node ;
152
+ }
153
+
154
+ private int checkIfNodeEmpty (AVLNode node ){
155
+ return (node == null ) ? (-1 ) : (node .height );
156
+ }
157
+
158
+ public boolean contains (int value ) {
159
+ return contains (value , this .root );
160
+ }
161
+
162
+ private boolean contains (int value , AVLNode root ) {
163
+ if (root == null ) return false ;
164
+ else if (root .value == value ) return true ;
165
+ else return contains (value , root .right ) || contains (value , root .left );
166
+ }
167
+
168
+ public int getDepth () {
169
+ return getDepth (this .root );
170
+ }
171
+
172
+ private int getDepth (AVLNode root ) {
173
+ if (root == null ) return 0 ;
174
+ if (root .left == null && root .right == null ) return 0 ;
175
+ return 1 + Math .max (getDepth (root .left ), getDepth (root .right ));
176
+ }
177
+
178
+ public LinkedList <Integer > getNodesAtDepth (int depth ) {
179
+ LinkedList <Integer > arr = new LinkedList <>();
180
+ getNodesAtDepth (depth , arr , this .root );
181
+ return arr ;
182
+ }
183
+
184
+ private void getNodesAtDepth (int depth , LinkedList <Integer > arr , AVLNode root ) {
185
+ if (root == null ) return ;
186
+ if (depth == 0 ) {
187
+ arr .addLast (root .value );
188
+ }
189
+ getNodesAtDepth (depth - 1 , arr , root .left );
190
+ getNodesAtDepth (depth - 1 , arr , root .right );
191
+ }
192
+
193
+ public void preOrderTraversal (){
194
+ preOrderTraversal (this .root );
195
+ }
196
+
197
+ private void preOrderTraversal (AVLNode root ){
198
+ if (root == null ) return ;
199
+ System .out .println (root .value );
200
+ preOrderTraversal (root .left );
201
+ preOrderTraversal (root .right );
202
+ }
203
+
204
+ public void inOrderTraversal (){
205
+ inOrderTraversal (this .root );
206
+ }
207
+
208
+ private void inOrderTraversal (AVLNode root ){
209
+ if (root == null ) return ;
210
+ preOrderTraversal (root .left );
211
+ System .out .println (root .value );
212
+ preOrderTraversal (root .right );
213
+ }
214
+
215
+ public void postOrderTraversal (){
216
+ postOrderTraversal (this .root );
217
+ }
218
+
219
+ private void postOrderTraversal (AVLNode root ){
220
+ if (root == null ) return ;
221
+ postOrderTraversal (root .left );
222
+ postOrderTraversal (root .right );
223
+ System .out .println (root .value );
224
+ }
225
+
226
+ public void BreadthFirst () {
227
+ for (int i = 0 ; i <= getDepth (); i ++) {
228
+ for (var temp : getNodesAtDepth (i )) System .out .print (temp + " " );
229
+ System .out .println ();
230
+ }
231
+ }
232
+ }
0 commit comments