View difference between Paste ID: FWvTDESx and uf0f69aX
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
}