SHOW:
|
|
- or go back to the newest paste.
1 | /* | |
2 | / Árvore AVL com Iteração e Comparação | |
3 | / | |
4 | / Especialidades: | |
5 | / -Auto balanceamento; | |
6 | / -É tipável; | |
7 | / -Possui um Comparator como atributo, ou seja, você decide como os elementos serão ordenados; | |
8 | / -Caso haja uma mudança no tipo de comparação, a árvore se re-ordena pelo novo comparador; | |
9 | / -É possível fazer busca por índice de posição; | |
10 | / -É possível fazer remoção por índice de posição; | |
11 | / -Guarda o número de nós adicionados; | |
12 | */ | |
13 | ||
14 | public class Link<E> { | |
15 | private E content; | |
16 | private int balancing; | |
17 | private Link left; | |
18 | private Link right; | |
19 | private Link father; | |
20 | public Link(E content) { | |
21 | this.content = content; | |
22 | this.balancing = 0; | |
23 | this.left = null; | |
24 | this.right = null; | |
25 | } | |
26 | public E getContent() { | |
27 | return content; | |
28 | } | |
29 | public void setContent(E content) { | |
30 | this.content = content; | |
31 | } | |
32 | public int getBalancing() { | |
33 | return balancing; | |
34 | } | |
35 | public void setBalancing(int balancing) { | |
36 | this.balancing = balancing; | |
37 | } | |
38 | public Link getLeft() { | |
39 | return left; | |
40 | } | |
41 | public void setLeft(Link left) { | |
42 | this.left = left; | |
43 | } | |
44 | public Link getRight() { | |
45 | return right; | |
46 | } | |
47 | public void setRight(Link right) { | |
48 | this.right = right; | |
49 | } | |
50 | public Link getFather() { | |
51 | return father; | |
52 | } | |
53 | public void setFather(Link father) { | |
54 | this.father = father; | |
55 | } | |
56 | } | |
57 | ||
58 | public class TreeIterator implements Iterator{ | |
59 | private Stack<Link> stack = new Stack<>(); | |
60 | ||
61 | public TreeIterator(Link root) { | |
62 | push(root); | |
63 | } | |
64 | @Override | |
65 | public boolean hasNext() { | |
66 | return !stack.isEmpty(); | |
67 | } | |
68 | @Override | |
69 | public Link next() { | |
70 | Link node = stack.pop(); | |
71 | push(node.getRight()); | |
72 | return node; | |
73 | } | |
74 | private void push(Link node) { | |
75 | while (node != null) { | |
76 | stack.push(node); | |
77 | node = node.getLeft(); | |
78 | } | |
79 | } | |
80 | } | |
81 | ||
82 | public class TreeLink<Generic> { | |
83 | private Link<Generic> root; | |
84 | private int size; | |
85 | private Comparator comparator; | |
86 | ||
87 | public TreeLink(Comparator comparator) { | |
88 | this.comparator = comparator; | |
89 | } | |
90 | public void addInTree(Generic content) { | |
91 | if(isEmpty()) addInRoot(content); | |
92 | else { | |
93 | Link<Generic> newLink = new Link<>(content); | |
94 | addInBranch(root, newLink); | |
95 | } | |
96 | size++; | |
97 | } | |
98 | public Generic removeByContent(Generic content) { | |
99 | Link<Generic> find = search(content); | |
100 | removeFoundLink(find); | |
101 | size--; | |
102 | return find.getContent(); | |
103 | } | |
104 | public Generic removeByPosition(int index) { | |
105 | if(index > size || index < 0) return null; | |
106 | else { | |
107 | return removeByContent(getByPosition(index)); | |
108 | } | |
109 | } | |
110 | public Link search(Generic content) { | |
111 | Link aux = root; | |
112 | if(aux != null) { | |
113 | while(aux != null) { | |
114 | if(comparator.compare(content, aux.getContent()) == 0) { | |
115 | return aux; | |
116 | } | |
117 | else if(comparator.compare(content, aux.getContent()) > 0) aux = aux.getRight(); | |
118 | else aux = aux.getLeft(); | |
119 | } | |
120 | } | |
121 | return null; | |
122 | } | |
123 | public void removeAll() { | |
124 | for(int i = 0; i < size; i++) | |
125 | removeByContent(getByPosition(i)); | |
126 | } | |
127 | public Generic getByPosition(int index) { | |
128 | if(index > size || index < 0) return null; | |
129 | else { | |
130 | Iterator it = iterator(); | |
131 | for(int i = 0; i < index; i++) | |
132 | it.next(); | |
133 | return (Generic) ((Link)it.next()).getContent(); | |
134 | } | |
135 | } | |
136 | public boolean isEmpty() { | |
137 | return size == 0; | |
138 | } | |
139 | public int size() { | |
140 | return size; | |
141 | } | |
142 | public Link getRoot() { | |
143 | return root; | |
144 | } | |
145 | public void display() { | |
146 | inOrder(root); | |
147 | } | |
148 | public void setComparator(Comparator comparator) { | |
149 | this.comparator = comparator; | |
150 | TreeLink newTree = new TreeLink(comparator); | |
151 | for(int i = 0; i < size; i++) | |
152 | newTree.addInTree(removeByPosition(i)); | |
153 | root = newTree.getRoot(); | |
154 | } | |
155 | private void addInRoot(Generic content) { | |
156 | root = new Link<>(content); | |
157 | } | |
158 | private void addInBranch(Link current, Link newLink) { | |
159 | if(comparator.compare(newLink.getContent(), current.getContent()) < 0) { | |
160 | if(current.getLeft() == null) { | |
161 | current.setLeft(newLink); | |
162 | newLink.setFather(current); | |
163 | checkBalance(current); | |
164 | } | |
165 | else { | |
166 | addInBranch(current.getLeft(), newLink); | |
167 | } | |
168 | } | |
169 | else if(comparator.compare(newLink.getContent(), current.getContent()) > 0) { | |
170 | if(current.getRight() == null) { | |
171 | current.setRight(newLink); | |
172 | newLink.setFather(current); | |
173 | checkBalance(current); | |
174 | } | |
175 | else { | |
176 | addInBranch(current.getRight(), newLink); | |
177 | } | |
178 | } | |
179 | } | |
180 | private void checkBalance(Link anyLink) { | |
181 | setBalancing(anyLink); | |
182 | int balancing = anyLink.getBalancing(); | |
183 | if(balancing == -2) { | |
184 | if(height(anyLink.getLeft().getLeft()) >= height(anyLink.getLeft().getRight())) { | |
185 | anyLink = singleRotationRight(anyLink); | |
186 | } | |
187 | else { | |
188 | anyLink = doubleRotationRight(anyLink); | |
189 | } | |
190 | } | |
191 | else if(balancing == 2) { | |
192 | if(height(anyLink.getRight().getRight()) >= height(anyLink.getRight().getLeft())) { | |
193 | anyLink = singleRotationLeft(anyLink); | |
194 | } | |
195 | else { | |
196 | anyLink = doubleRotationLeft(anyLink); | |
197 | } | |
198 | } | |
199 | if(anyLink.getFather() != null) { | |
200 | checkBalance(anyLink.getFather()); | |
201 | } | |
202 | else { | |
203 | this.root = anyLink; | |
204 | } | |
205 | } | |
206 | private void removeFoundLink(Link find) { | |
207 | Link aux1; | |
208 | if(find.getLeft() == null || find.getRight() == null) { | |
209 | if(find.getFather() == null) { | |
210 | root = null; | |
211 | find = null; | |
212 | return; | |
213 | } | |
214 | aux1 = find; | |
215 | } | |
216 | else { | |
217 | aux1 = nextLink(find); | |
218 | find.setContent(aux1.getContent()); | |
219 | } | |
220 | Link aux2; | |
221 | if(aux1.getLeft() != null) { | |
222 | aux2 = aux1.getLeft(); | |
223 | } | |
224 | else { | |
225 | aux2 = aux1.getRight(); | |
226 | } | |
227 | if(aux2 != null) { | |
228 | aux2.setFather(aux1.getFather()); | |
229 | } | |
230 | if(aux1.getFather() == null) { | |
231 | root = aux2; | |
232 | } | |
233 | else { | |
234 | if(aux1 == aux1.getFather().getLeft()) { | |
235 | aux1.getFather().setLeft(aux2); | |
236 | } | |
237 | else { | |
238 | aux1.getFather().setRight(aux2); | |
239 | } | |
240 | checkBalance(aux1.getFather()); | |
241 | } | |
242 | aux1 = null; | |
243 | } | |
244 | private Link singleRotationLeft(Link anyLink) { | |
245 | Link linkRight = anyLink.getRight(); | |
246 | linkRight.setFather(anyLink.getFather()); | |
247 | anyLink.setRight(linkRight.getLeft()); | |
248 | if(anyLink.getRight() != null) { | |
249 | anyLink.getRight().setFather(anyLink); | |
250 | } | |
251 | linkRight.setLeft(anyLink); | |
252 | anyLink.setFather(linkRight); | |
253 | if(linkRight.getFather() != null) { | |
254 | if(linkRight.getFather().getRight() == anyLink) { | |
255 | linkRight.getFather().setRight(linkRight); | |
256 | } | |
257 | else if(linkRight.getFather().getLeft() == anyLink) { | |
258 | linkRight.getFather().setLeft(linkRight); | |
259 | } | |
260 | } | |
261 | setBalancing(anyLink); | |
262 | setBalancing(linkRight); | |
263 | return linkRight; | |
264 | } | |
265 | private Link singleRotationRight(Link anyLink) { | |
266 | Link linkLeft = anyLink.getLeft(); | |
267 | linkLeft.setFather(anyLink.getFather()); | |
268 | anyLink.setLeft(linkLeft.getRight()); | |
269 | if(anyLink.getLeft() != null) { | |
270 | anyLink.getLeft().setFather(anyLink); | |
271 | } | |
272 | linkLeft.setRight(anyLink); | |
273 | anyLink.setFather(linkLeft); | |
274 | if(linkLeft.getFather() != null) { | |
275 | if(linkLeft.getFather().getRight() == anyLink) { | |
276 | linkLeft.getFather().setRight(linkLeft); | |
277 | } | |
278 | else if(linkLeft.getFather().getLeft() == anyLink) { | |
279 | linkLeft.getFather().setLeft(linkLeft); | |
280 | } | |
281 | } | |
282 | setBalancing(anyLink); | |
283 | setBalancing(linkLeft); | |
284 | return linkLeft; | |
285 | } | |
286 | private Link doubleRotationRight(Link anyLink) { | |
287 | anyLink.setLeft(singleRotationLeft(anyLink.getLeft())); | |
288 | return singleRotationRight(anyLink); | |
289 | } | |
290 | private Link doubleRotationLeft(Link anyLink) { | |
291 | anyLink.setRight(singleRotationRight(anyLink.getRight())); | |
292 | return singleRotationLeft(anyLink); | |
293 | } | |
294 | private Link nextLink(Link anyLink) { | |
295 | if (anyLink.getRight() != null) { | |
296 | Link aux = anyLink.getRight(); | |
297 | while (aux.getLeft() != null) | |
298 | aux = aux.getLeft(); | |
299 | return aux; | |
300 | } | |
301 | else { | |
302 | Link aux = anyLink.getFather(); | |
303 | while (aux != null && anyLink == aux.getRight()) { | |
304 | anyLink = aux; | |
305 | aux = anyLink.getFather(); | |
306 | } | |
307 | return aux; | |
308 | } | |
309 | } | |
310 | private int height(Link anyLink) { | |
311 | if (anyLink == null) { | |
312 | return -1; | |
313 | } | |
314 | if (anyLink.getLeft() == null && anyLink.getRight() == null) { | |
315 | return 0; | |
316 | } | |
317 | else if (anyLink.getLeft() == null) { | |
318 | return 1 + height(anyLink.getRight()); | |
319 | } | |
320 | else if (anyLink.getRight() == null) { | |
321 | return 1 + height(anyLink.getLeft()); | |
322 | } | |
323 | else { | |
324 | return 1 + Math.max(height(anyLink.getLeft()), height(anyLink.getRight())); | |
325 | } | |
326 | } | |
327 | private void setBalancing(Link anyLink) { | |
328 | anyLink.setBalancing(height(anyLink.getRight()) - height(anyLink.getLeft())); | |
329 | } | |
330 | private void inOrder(Link anyLink) { | |
331 | if (anyLink == null) { | |
332 | return; | |
333 | } | |
334 | inOrder(anyLink.getLeft()); | |
335 | System.out.println(anyLink.getContent()); | |
336 | inOrder(anyLink.getRight()); | |
337 | } | |
338 | private Iterator iterator() { | |
339 | return new TreeIterator(root); | |
340 | } | |
341 | } |